#!/usr/bin/env python3

from zope.component import getUtility

from twisted.application.internet import TCPServer
from twisted.application.service import Application
from twisted.internet import reactor
from twisted.web.resource import Resource
from twisted.web.http import OK

from storm.twisted.transact import Transactor

from canonical.amqp.message.interfaces import IPublisher
from canonical.twisted.site import MaxMemorySite

from canonical.landscape.setup import load_config, setup_broker
from canonical.landscape.pingserver.pingserver import (
    ComputersNeedingNotification, WebPing)
from canonical.landscape.scripts.pingserver import run


if __name__ == "__main__":
    run()


# Interval at which to check the database for computers with outstanding
# messages
CHECK_INTERVAL = 30

# Interval at which to write last_ping_time updates
WRITE_INTERVAL = 60

# Default base port to listen on
LISTEN_PORT = 8081

# Default number of threads to use
MAX_THREADS = 2

config = load_config("pingserver")
pingserver_config = config.get("pingserver")
global_config = config.get("global")

port = int(pingserver_config.get("port", LISTEN_PORT))

application = Application("pingserver")

threadpool = reactor.getThreadPool()

transactor = Transactor(threadpool)

check_interval = int(pingserver_config.get("database-check-interval",
                                           CHECK_INTERVAL))
write_interval = int(pingserver_config.get("database-write-interval",
                                           WRITE_INTERVAL))

cnn = ComputersNeedingNotification(transactor)
cnn.start(check_interval, write_interval)
cnn.tracker.set_window_duration(
    int(pingserver_config.get(
        "pingtracker-window-duration", cnn.tracker.window_duration)))
cnn.tracker.set_window_ping_limit(
    int(pingserver_config.get(
        "pingtracker-window-ping-limit", cnn.tracker.window_ping_limit)))
cnn.tracker.set_penalty_window_duration(
    int(pingserver_config.get(
        "pingtracker-penalty-window-duration",
        cnn.tracker.penalty_window_duration)))


class Head(Resource):
    """Serve responses to HEAD health checks."""

    isLeaf = True

    def render_HEAD(self, request):
        request.setHeader("Content-Type", "text/plain")
        request.setResponseCode(OK)
        return b""


root = Resource()
root.putChild(b"ping", WebPing(cnn.tracker.ping))
root.putChild(b"", Head())
site = MaxMemorySite(root, max_memory_mib=int(global_config.get("max-service-memory", 0)))
site.displayTracebacks = False
TCPServer(port, site).setServiceParent(application)

publisher = getUtility(IPublisher)

setup_broker(config, publisher.connected, publisher.disconnected, application)
