import re
from typing import Tuple, Optional

import parse

from app.core.meta.metabase import MetaBase


class FormatParser(object):
    _key = ""
    _split_chars = r"\.|\s+|\(|\)|\[|]|-|\+|【|】|/|～|;|&|\||#|_|「|」|~"

    def __init__(self, eformat: str, details: Optional[str] = None, part: Optional[str] = None,
                 offset: Optional[str] = None, key: Optional[str] = "ep"):
        """
        :params eformat: 格式化字符串
        :params details: 格式化详情
        :params part: 分集
        :params offset: 偏移量 -10/EP*2
        :prams key: EP关键字
        """
        self._format = eformat
        self._start_ep = None
        self._end_ep = None
        if not offset:
            self.__offset = "EP"
        elif "EP" in offset:
            self.__offset = offset
        else:
            if offset.startswith("-") or offset.startswith("+"):
                self.__offset = f"EP{offset}"
            else:
                self.__offset = f"EP+{offset}"
        self._key = key
        self._part = None
        if part:
            self._part = part
        if details:
            if re.compile("\\d{1,4}-\\d{1,4}").match(details):
                self._start_ep = details
                self._end_ep = details
            else:
                tmp = details.split(",")
                if len(tmp) > 1:
                    self._start_ep = int(tmp[0])
                    self._end_ep = int(tmp[0]) if int(tmp[0]) > int(tmp[1]) else int(tmp[1])
                else:
                    self._start_ep = self._end_ep = int(tmp[0])

    @property
    def format(self):
        return self._format

    @property
    def start_ep(self):
        return self._start_ep

    @property
    def end_ep(self):
        return self._end_ep

    @property
    def part(self):
        return self._part

    @property
    def offset(self):
        return self.__offset

    def match(self, file: str) -> bool:
        if not self._format:
            return True
        s, e = self.__handle_single(file)
        if not s:
            return False
        if self._start_ep is None:
            return True
        if self._start_ep <= s <= self._end_ep:
            return True
        return False

    def split_episode(self, file_name: str, file_meta: MetaBase) -> Tuple[Optional[int], Optional[int], Optional[str]]:
        """
        拆分集数，返回开始集数，结束集数，Part信息
        """
        # 指定的具体集数，直接返回
        if self._start_ep is not None:
            if self._start_ep == self._end_ep:
                # `details` 格式为 `X-X` 或者 `X`
                if isinstance(self._start_ep, str):
                    # `details` 格式为 `X-X`
                    s, e = self._start_ep.split("-")
                    start_ep = self.__offset.replace("EP", s)
                    end_ep = self.__offset.replace("EP", e)
                    if int(s) == int(e):
                        return int(eval(start_ep)), None, self.part
                    return int(eval(start_ep)), int(eval(end_ep)), self.part
                else:
                    # `details` 格式为 `X`
                    start_ep = self.__offset.replace("EP", str(self._start_ep))
                    return int(eval(start_ep)), None, self.part
            elif not self._format:
                # `details` 格式为 `X,X`
                start_ep = self.__offset.replace("EP", str(self._start_ep))
                end_ep = self.__offset.replace("EP", str(self._end_ep))
                return int(eval(start_ep)), int(eval(end_ep)), self.part
        if not self._format:
            # 未填入`集数定位` 且没有`指定集数` 仅处理`集数偏移`
            start_ep = eval(self.__offset.replace("EP", str(file_meta.begin_episode))) if file_meta.begin_episode else None
            end_ep = eval(self.__offset.replace("EP", str(file_meta.end_episode))) if file_meta.end_episode else None
            return int(start_ep) if start_ep else None, int(end_ep) if end_ep else None, self.part
        else:
            # 有`集数定位`
            s, e = self.__handle_single(file_name)
            start_ep = self.__offset.replace("EP", str(s)) if s else None
            end_ep = self.__offset.replace("EP", str(e)) if e else None
            return int(eval(start_ep)) if start_ep else None, int(eval(end_ep)) if end_ep else None, self.part

    def __handle_single(self, file: str) -> Tuple[Optional[int], Optional[int]]:
        """
        处理单集，返回单集的开始和结束集数
        """
        if not self._format:
            return None, None
        ret = parse.parse(self._format, file)
        if not ret or not ret.__contains__(self._key):
            return None, None
        episodes = ret.__getitem__(self._key)
        if not re.compile(r"^(EP)?(\d{1,4})(-(EP)?(\d{1,4}))?$", re.IGNORECASE).match(episodes):
            return None, None
        episode_splits = list(filter(lambda x: re.compile(r'[a-zA-Z]*\d{1,4}', re.IGNORECASE).match(x),
                                     re.split(r'%s' % self._split_chars, episodes)))
        if len(episode_splits) == 1:
            return int(re.compile(r'[a-zA-Z]*', re.IGNORECASE).sub("", episode_splits[0])), None
        else:
            return int(re.compile(r'[a-zA-Z]*', re.IGNORECASE).sub("", episode_splits[0])), int(
                re.compile(r'[a-zA-Z]*', re.IGNORECASE).sub("", episode_splits[1]))
