import json
from typing import List, Dict



from tz_objects.timezone_json_data import TimeZoneJsonData
from tz_objects.tz_json_metadata import TzJsonMetadata

TBD_ID_STR = 'TBD'

TZ_JSON_KEY_MAP = {
    "CTM-CODE": "ctm_code",
    "UI-NAME": "ui_name",
    "ID": "id",
    "CODE": "code",
    "NAME": "name",
    "DST-GMT-OFFSET-SIGN": "dst_gmt_offset_sign",
    "DST-GMT-OFFSET-HOUR": "dst_gmt_offset_hour",
    "DST-GMT-OFFSET-MINUTE": "dst_gmt_offset_minute",
    "DST-OFFSET-SIGN": "dst_offset_sign",
    "DST-OFFSET-HOUR": "dst_offset_hour",
    "DST-OFFSET-MINUTE": "dst_offset_minute",
    "OFFSET-SIGN": "offset_sign",
    "OFFSET-HOUR": "offset_hour",
    "OFFSET-MINUTE": "offset_minute",
    "HAS-DST": "has_dst",
    "SHOW-UI": "show_ui",
    "DST-FROM-YEAR": "dst_from_year",
    "DST-FROM-MONTH": "dst_from_month",
    "DST-FROM-DAY": "dst_from_day",
    "DST-FROM-HOUR": "dst_from_hour",
    "DST-FROM-MINUTE": "dst_from_minute",
    "DST-TO-YEAR": "dst_to_year",
    "DST-TO-MONTH": "dst_to_month",
    "DST-TO-DAY": "dst_to_day",
    "DST-TO-HOUR": "dst_to_hour",
    "DST-TO-MINUTE": "dst_to_minute",
}


def _rename_tz_json_keys(obj):
    if isinstance(obj, dict):
        return {TZ_JSON_KEY_MAP.get(key, key): _rename_tz_json_keys(value) for key, value in obj.items()}
    if isinstance(obj, list):
        return [_rename_tz_json_keys(item) for item in obj]
    return obj


def translate_tz_json_to_object_fildes_fromat(input: str):
    return json.dumps(_rename_tz_json_keys(json.loads(input)))


class TimeZoneJson :
    def __init__(self, metadata: TzJsonMetadata, data: List[TimeZoneJsonData]):
        self.metadata = metadata
        self.data = data

    @staticmethod
    def from_file(json_file_path: str):
        with open(json_file_path, 'r', encoding='utf-8') as file:
            json_str = file.read()

        json_str = translate_tz_json_to_object_fildes_fromat(json_str)

        json_dict = json.loads(json_str)
        # manipulate file so at can be loaded by TimeZoneJsinCostructor

        medatadta_dict =json_dict['metadata']

        metadata = TzJsonMetadata(medatadta_dict['createdDate'],medatadta_dict['tzdataVersion'])
        data = [TimeZoneJsonData(**tz) for tz in json_dict['data']]
        return TimeZoneJson(metadata, data)

    def to_dict(self):
        return {
            "metadata": {
                "createdDate": self.metadata.createdDate,
                "tzdataVersion": self.metadata.tzdataVersion},
            "data": [item.to_dict() for item in self.data]  # Serialize each TimeZoneJsonData object
        }

    def to_file(self, file_path: str):
        with open(file_path, 'w', encoding='utf-8') as file:
            json.dump(self.to_dict(), file, indent=4)

    def get_timezones_by_gmt(self, hour_offset, minute_offset, sign) -> List[TimeZoneJsonData]:
        time_zones_list = []
        for timezone in self.data:
            if timezone.is_matching_gmt(hour_offset, minute_offset, sign):
                time_zones_list.append(timezone)

        time_zones_list.append(
            TimeZoneJsonData(ctm_code=None, id=TBD_ID_STR ,code=None, name=None, offset_sign=None, offset_hour=None,
                             offset_minute=None, has_dst=False, show_ui=False))
        return time_zones_list

    def get_timezones_data_dictionary_by_ctm_code(self) -> Dict[str, TimeZoneJsonData]:
        dict = {obj.ctm_code: obj for obj in self.data}
        return dict

    def get_timezones_data_dictionary_by_IANA_id(self) -> Dict[str, TimeZoneJsonData]:
        dict = {obj.id: obj for obj in self.data}
        return dict

    def get_ctm_codes_set(self) -> set:
        return set([obj.ctm_code for obj in self.data if obj.ctm_code is not None])

    def add_tz_data(self, tz_data: TimeZoneJsonData):
        self.data.append(tz_data)
