import json
from datetime import datetime
from typing import Any

import pytz
import tornado
from tornado import httputil
from tornado.web import Application

from core.config import MAX_SPOT_AGE, ALLOW_SPOTTING
from core.constants import BANDS, ALL_MODES, MODE_TYPES, SIGS, CONTINENTS
from core.prometheus_metrics_handler import api_requests_counter
from core.utils import serialize_everything


class APIOptionsHandler(tornado.web.RequestHandler):
    """API request handler for /api/v1/options"""

    def __init__(self, application: "Application", request: httputil.HTTPServerRequest, **kwargs: Any):
        self._status_data = None
        self._web_server_metrics = None
        super().__init__(application, request, **kwargs)

    def initialize(self, status_data, web_server_metrics):
        self._status_data = status_data
        self._web_server_metrics = web_server_metrics

    def get(self):
        # Metrics
        self._web_server_metrics["last_api_access_time"] = datetime.now(pytz.UTC)
        self._web_server_metrics["api_access_counter"] += 1
        self._web_server_metrics["status"] = "OK"
        api_requests_counter.inc()

        options = {"bands": BANDS,
                   "modes": ALL_MODES,
                   "mode_types": MODE_TYPES,
                   "sigs": SIGS,
                   # Spot/alert sources are filtered for only ones that are enabled in config, no point letting the user toggle things that aren't even available.
                   "spot_sources": list(
                       map(lambda p: p["name"], filter(lambda p: p["enabled"], self._status_data["spot_providers"]))),
                   "alert_sources": list(
                       map(lambda p: p["name"], filter(lambda p: p["enabled"], self._status_data["alert_providers"]))),
                   "continents": CONTINENTS,
                   "max_spot_age": MAX_SPOT_AGE,
                   "spot_allowed": ALLOW_SPOTTING}
        # If spotting to this server is enabled, "API" is another valid spot source even though it does not come from
        # one of our proviers.
        if ALLOW_SPOTTING:
            options["spot_sources"].append("API")

        self.write(json.dumps(options, default=serialize_everything))
        self.set_status(200)
        self.set_header("Cache-Control", "no-store")
        self.set_header("Content-Type", "application/json")
