""" Ether web service """
import asyncio
import logging
from asyncio import AbstractEventLoop
from threading import Thread, Lock
from typing import List, Dict, Optional

from aiohttp import web

from utils.ether_service.entities.receiver import Receiver
from utils.ether_service.handlers.api.v1.ws import WSHandler
from utils.ether_service.utils import ProcessService
from utils.run_app_fixed import create_task
from utils.ws_client import WSClient

logger = logging.getLogger(__name__)


class EtherService(Thread):
    """ Ether Service. This is a thread that runs aiohttp.
        Main purpose is:
        1. Receive data from KrSPIs.
        2. Do math on the background.
        3. Update global variables for the obsolete web service."""

    def __init__(self, web_service: "BottleWebServer",
                 db_writer: "DatabaseWriter",
                 shared_dict: Dict,
                 ws_client: WSClient,
                 receiver_controller: ProcessService,
                 *,
                 io_loop: Optional[AbstractEventLoop] = None,
                 interface="0.0.0.0", port=8090):
        super().__init__(name=self.__class__.__name__, daemon=True)
        self.web_service = web_service
        self.db_writer = db_writer
        self.shared_dict = shared_dict
        self.ws_client = ws_client
        self.receiver_controller = receiver_controller

        self._is_running = False
        self._is_running_lock = Lock()

        self.interface = interface
        self.port = port

        self.io_loop = io_loop or asyncio.get_event_loop()
        self.web_app = web.Application()
        self.web_app.add_routes([
            WSHandler().compile(),
        ])
        self.main_task = None

    @property
    def is_running(self):
        """ Get _is_running safely """
        with self._is_running_lock:
            return self._is_running

    @is_running.setter
    def is_running(self, value: bool):
        """ set _is_running safely """
        with self._is_running_lock:
            self._is_running = value

    def run(self):
        """ Thread routine """
        self.is_running = True
        # self.main_task = create_task(self.web_app, host=self.interface,
        #                              port=self.port, loop=self.io_loop,
        #                              handle_signals=False,
        #                              print=lambda x: x)
        logger.info("Server has started")
        self.io_loop.run_forever()
        logger.info("Server has stopped")

    def start(self):
        """ Start the app """
        logger.info("Server is starting")
        super().start()

    def stop(self):
        """ Stop the app """
        logger.info("Server is stopping")
        self.is_running = False
        # self.web_service.stop()  # How do we stop this crap ?
        self.db_writer.stop()
        self.receiver_controller.stop()
        if self.main_task is not None:
            self.io_loop.call_soon_threadsafe(self.main_task.cancel)
        self.io_loop.call_soon_threadsafe(self.io_loop.stop)
