#  Copyright (c) 2025  Jeffrey Hsu - JITToolBox
#  #
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#  #
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  #
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
import json
from abc import ABC, abstractmethod
from os import PathLike
from typing import Optional


class BaseExcelConfig(ABC):
    @property
    @abstractmethod
    def name(self) -> str:
        ...

    @property
    @abstractmethod
    def position(self) -> str:
        ...


class RangeExcelConfigMixin(ABC):
    @property
    @abstractmethod
    def start(self) -> int:
        ...

    @property
    @abstractmethod
    def end(self) -> Optional[int]:
        ...

    @property
    @abstractmethod
    def fposition(self) -> str:
        ...


class SingleExcelConfigItem(BaseExcelConfig):

    def __init__(self, name: str, position: str):
        self._name = name
        self._position = position

    @property
    def name(self) -> str:
        return self._name

    @property
    def position(self) -> str:
        return self._position


class RangeExcelConfigItem(SingleExcelConfigItem, RangeExcelConfigMixin):

    def __init__(self, name: str, position: str, start: int, end: Optional[int] = None):
        super().__init__(name, position)
        self._start = start
        self._end = end

    @property
    def start(self) -> int:
        return self._start

    @property
    def end(self) -> Optional[int]:
        return self._end

    @property
    def fposition(self) -> str:
        return self.position + '{}'


class AESConfig:
    _config_list: list[SingleExcelConfigItem | RangeExcelConfigItem]

    def __init__(self, file_path: str | PathLike):
        self._file_path = file_path
        self._config_list = []
        self._init_config()

    def __getitem__(self, item: str):
        return self.get_config(item)

    def _init_config(self):
        with open(self._file_path, 'r', encoding='utf-8') as f:
            config = json.load(f)
            f.close()

        for item in config['config']:
            itype = item.pop('type', None)
            if itype == 'range':
                self._config_list.append(RangeExcelConfigItem(**item))
            elif itype == 'single':
                self._config_list.append(SingleExcelConfigItem(**item))

    def get_config(self, name: str) -> Optional[RangeExcelConfigItem | SingleExcelConfigItem]:
        for config in self._config_list:
            if config.name == name:
                return config
        return None
