import json
import time

import requests
from requests import ReadTimeout
from torpy.http.requests import do_request

from core.db import DB
from core.decorators import instance
from core.dict_object import DictObject
from core.logger import Logger


@instance()
class CharacterHistoryService:
    CACHE_GROUP = "history"
    CACHE_MAX_AGE = 86400
    users = []

    def __init__(self):
        self.logger = Logger(__name__)

    def inject(self, registry):
        self.bot = registry.get_instance("bot")
        self.db: DB = registry.get_instance("db")
        self.cache_service = registry.get_instance("cache_service")

    def get_character_history(self, name, server_num):
        cache_key = "%s.%d.json" % (name, server_num)

        t = int(time.time())

        # check cache for fresh value
        cache_result = self.cache_service.retrieve(self.CACHE_GROUP, cache_key)
        if cache_result and cache_result.last_modified > (t - self.CACHE_MAX_AGE):
            result = json.loads(cache_result.data)
        else:
            url = self.get_pork_url(server_num, name)
            try:
                r = do_request(url)
                # with TorRequests() as tor_request:
                #     with tor_request.get_session(1) as session:
                #         r = session.get(url, timeout=5)
                # r = requests.get(url, timeout=5, headers={"User-Agent": self.bot.major_version})
                result = json.loads(r)
            except ReadTimeout:
                self.logger.warning(f"Timeout while requesting '{url}'")
                result = None
            except Exception as e:
                self.logger.error(f"Error requesting history for url '{url}'", e)
                result = None

            if result:
                # store result in cache
                self.cache_service.store(self.CACHE_GROUP, cache_key, json.dumps(result))
            elif cache_result:
                # check cache for any value, even expired
                result = json.loads(cache_result.data)

        if result:
            return map(lambda x: DictObject(x), result)
        else:
            return None

    def get_pork_url(self, dimension, char_name):
        # noinspection HttpUrlsUsage
        return f"http://pork.budabot.jkbff.com/pork/history.php?server={dimension:d}&name={char_name}"
