import errno
import logging
import os
import re
import time

from datetime import datetime
from dateutil import relativedelta
from msgbus import (
    TK_SYS_NAK,
    TK_POS_GETPOSLIST,
    FM_PARAM,
    MBEasyContext
)
from typing import (
    Any,
    List,
    Optional,
    Union
)

from model.exception import PosListException

logger = logging.getLogger("Maintenance")


class CommonService(object):

    def __init__(
        self,
        mb_context,             # type: MBEasyContext
        months_to_keep_data,    # type: int
    ):
        # type: (...) -> None

        self.mb_context = mb_context
        self.months_to_keep_data = months_to_keep_data

        self.pos_list = None  # type: Optional[List[str]]

    def get_pos_list(
        self
    ):
        # type: () -> List[str]

        if self.pos_list:
            return self.pos_list

        try:
            msg = self.mb_context.MB_EasySendMessage('PosController', TK_POS_GETPOSLIST, FM_PARAM)
            if msg.token == TK_SYS_NAK or not msg.data:
                raise PosListException()

            self.pos_list = msg.data.split("\0")
            self.pos_list.sort(key=lambda x: int(x))
            return self.pos_list
        except Exception:
            logger.exception("Error getting the list of POS")

    @staticmethod
    def delete_files(
        files_to_delete     # type: List[str]
    ):
        # type: (...) -> None

        logger.info("Delete files process started. files_to_delete: {}".format(files_to_delete))
        try:
            for file_name in files_to_delete:
                dirname = os.path.dirname(file_name)
                filename = os.path.basename(file_name)
                if os.path.isdir(dirname):
                    for f in os.listdir(dirname):
                        if re.search(filename, f):
                            os.remove(os.path.join(dirname, f))
        except OSError as _:
            logger.exception("Error deleting files. files_to_delete: {}".format(files_to_delete))

    @staticmethod
    def make_sure_path_exists(
        path    # type: str
    ):
        # type: (...) -> None

        try:
            os.makedirs(path)
        except OSError as ex:
            if ex.errno != errno.EEXIST:
                raise

    def get_end_date(
        self,
        timestamp=False,    # type: Optional[bool]
    ):
        # type: (...) -> Any[Union[str, int]]

        current_month = datetime.now().replace(day=1, hour=0, minute=0, second=0, microsecond=0)
        end_date = current_month - relativedelta.relativedelta(months=self.months_to_keep_data)

        if timestamp:
            return int(time.mktime(end_date.timetuple()))

        return end_date.strftime("%Y%m%d")

    @staticmethod
    def get_file_size(
        file_name   # type: str
    ):
        # type: (...) -> int

        return os.path.getsize(file_name) / 1024 / 1024
