import asyncio
from typing import Optional

from aiohttp import web

from smb.common.multiruntime.lib.io import setup_filesystem

from maps_adv.manul.lib.api_providers import ClientsApiProvider, OrdersApiProvider
from maps_adv.manul.lib.data_managers import ClientsDataManager, OrdersDataManager

from . import api
from .db import DB

setup_filesystem("maps_adv/manul/")


class Application:
    def __init__(self, config):
        self._config = config

    def run(self, host: Optional[str] = None, port: Optional[int] = None):
        web.run_app(self._run(), host=host, port=port, loop=asyncio.get_event_loop())

    async def _run(self) -> web.Application:
        db = await DB.create(self._config.DATABASE_URL)
        api = self.setup(db)
        api.on_shutdown.append(lambda app: db.close())
        return api

    def setup(self, db: DB) -> web.Application:
        clients_dm = ClientsDataManager(db)
        orders_dm = OrdersDataManager(db)

        clients_provider = ClientsApiProvider(clients_dm)
        orders_provider = OrdersApiProvider(orders_dm)

        _api = api.create(db, clients_provider, orders_provider)

        return _api
