
import tornado.gen

from tornado.gen import sleep, Future
from tornado.httpclient import HTTPRequest, HTTPError
from tornado.simple_httpclient import SimpleAsyncHTTPClient

from .. import options as _opts
from anthill.common.internal import Internal, InternalError
from anthill.common.validate import validate_value
from anthill.common.server import Server
from . util import promise, PromiseContext, APIError

API_TIMEOUT = 5


# noinspection PyUnusedLocal
@promise
async def sleep(delay, handler=None):
    await tornado.gen.sleep(delay)


# noinspection PyUnusedLocal
@promise
async def moment(handler=None):
    await tornado.gen.moment


def log(message):
    handler = PromiseContext.current
    if handler:
        handler.log(message)


class AdminAPI(object):
    @promise
    async def delete_accounts(self, accounts, gamespace_only=True, handler=None, *args, **kwargs):
        application = Server.instance()

        publisher = await application.acquire_publisher()

        await publisher.publish("DEL", {
            "gamespace": handler.env["gamespace"],
            "accounts": accounts,
            "gamespace_only": gamespace_only
        })


# noinspection PyUnusedLocal
class WebAPI(object):
    def __init__(self):
        self.http_client = SimpleAsyncHTTPClient()
        self.rc_cache = {}

    @promise
    async def get(self, url, headers=None, *args, **kwargs):
        request = HTTPRequest(url=url, use_gzip=True, headers=headers)

        existing_futures = self.rc_cache.get(url, None)

        if existing_futures is not None:
            future = Future()
            existing_futures.append(future)
            result = await future
            return result

        new_futures = []
        self.rc_cache[url] = new_futures

        try:
            response = await self.http_client.fetch(request)
        except HTTPError as e:
            e = APIError(e.code, e.message)

            for future in new_futures:
                future.set_exception(e)

            del self.rc_cache[url]
            raise e
        else:
            body = response.body

            for future in new_futures:
                future.set_result(body)

            del self.rc_cache[url]

        return body


# noinspection PyUnusedLocal
class ConfigAPI(object):
    @promise