import time
import json
import logging
from typing import List
import redis


from algo.data.common import PricePoint
from algo.config import config


log = logging.getLogger(__name__)


class RedisCache:
    def __init__(self) -> None:
        self._redis_connection = None

    def _init_redis_connection(self, force_reconnect=False):
        if force_reconnect or self._redis_connection is None:
            self._redis_connection: redis.Redis = redis.Redis.from_url(
                config.redis_url
            )

    def has_lock(self, cache_key: str):
        """TODO: implement lock with appropriate redis tools despite of workaround"""
        self._init_redis_connection()
        return self._redis_connection.get(cache_key) is not None

    def set_lock(self, cache_key: str):
        self._init_redis_connection()
        lock_is_set = False
        while not lock_is_set:
            try:
                self._redis_connection.set(cache_key, 1)
                lock_is_set = True
            except redis.ReadOnlyError as read_only_error:
                log.error(
                    'redis:ReadOnlyError', extra={'e': read_only_error}
                )
                time.sleep(1.0)
                self._init_redis_connection(True)

    def clear_lock(self, cache_key: str):
        self._init_redis_connection()
        return self._redis_connection.delete(cache_key)

    def has(self, cache_key: str):
        self._init_redis_connection()
        return self._redis_connection.get(cache_key) is not None

    def get(self, cache_key: str):
        """
        may be generator. Usage uf ujson may improve performance as this class essenstially does unjsoning
        """
        self._init_redis_connection()
        data = self._redis_connection.get(cache_key)
        all_data = []

        for data_portion in json.loads(data):
            all_data.append(PricePoint.from_json_ready(data_portion))

        return all_data

    def set(self, cache_key: str, data: List[PricePoint]):
        self._init_redis_connection()
        json_ready_data = []
        for data_portion in data:
            json_ready_data.append(data_portion.to_json_ready())
        serialized_data = json.dumps(json_ready_data)
        self._redis_connection.set(cache_key, serialized_data)
