from ctyun.man.model.request import Request
import xml.sax
from ctyun.util.utils import XMLHandler
from ctyun.result import Result
from ctyun.result import ResponseHeader
from xml.dom.minidom import parseString
from ctyun.man.model.baseStatistics import BaseStatistics


class GetReturnCodeRequest(Request):

    def __init__(self, BeginDate=None, EndDate=None, Bucket=None, Region=None, Freq=None, InternetType=None,
                 RequestsType=None, ResponseType=None, StorageClass=None):
        self.BeginDate = BeginDate
        self.EndDate = EndDate
        self.Bucket = Bucket
        self.Region = Region
        self.Freq = Freq
        self.StorageClass = StorageClass
        self.RequestsType = RequestsType
        self.InternetType = InternetType
        self.ResponseType = ResponseType

    def get_params(self):
        params = {"Action": "GetReturnCode"}
        if self.BeginDate is not None:
            params['BeginDate'] = self.BeginDate
        if self.EndDate is not None:
            params['EndDate'] = self.EndDate
        if self.Bucket is not None:
            params['Bucket'] = self.Bucket
        if self.Region is not None:
            params['Region'] = self.Region
        if self.Freq is not None:
            params['Freq'] = self.Freq
        if self.StorageClass is not None:
            params['StorageClass'] = self.StorageClass
        if self.InternetType is not None:
            params['InternetType'] = self.InternetType
        if self.RequestsType is not None:
            params['RequestsType'] = self.RequestsType
        if self.ResponseType is not None:
            params['ResponseType'] = self.ResponseType
        return params


class ReturnCodeStatistics(BaseStatistics):
    OBJ_TEMPLATE = (
            "\n     ReturnCode Statistic {order}: \n"
            + "       Date: {date}, "
            + "\n"
            + "       {storage_class} Data:  \n"
            + "       Internet-Data-Get:  "
            + "\n"
            + "       Response200: {Get200},"
            + "       Response206: {Get206},"
            + "       Response403: {Get403},"
            + "       Response404: {Get404},"
            + "       Response4xx: {Get4xx},"
            + "       Response500: {Get500},"
            + "       Response503: {Get503},"
            + "\n"
            + "       Internet-Data-Head:  "
            + "\n"
            + "       Response200: {Head200},"
            + "       Response206: {Head206},"
            + "       Response403: {Head403},"
            + "       Response404: {Head404},"
            + "       Response4xx: {Head4xx},"
            + "       Response500: {Head500},"
            + "       Response503: {Head503},"
            + "\n"
            + "       Internet-Data-Put:  "
            + "\n"
            + "       Response200: {Put200},"
            + "       Response403: {Put403},"
            + "       Response404: {Put404},"
            + "       Response4xx: {Put4xx},"
            + "       Response500: {Put500},"
            + "       Response503: {Put503},"
            + "\n"
            + "       Internet-Data-Post:  "
            + "\n"
            + "       Response200: {Post200},"
            + "       Response403: {Post403},"
            + "       Response404: {Post404},"
            + "       Response4xx: {Post4xx},"
            + "       Response500: {Post500},"
            + "       Response503: {Post503},"
            + "\n"
            + "       Internet-Data-Delete:  "
            + "\n"
            + "       Response200: {Delete200},"
            + "       Response204: {Delete204},"
            + "       Response403: {Delete403},"
            + "       Response404: {Delete404},"
            + "       Response4xx: {Delete4xx},"
            + "       Response500: {Delete500},"
            + "       Response503: {Delete503},"
            + "\n"
            + "       Internet-Data-Others:  "
            + "\n"
            + "       Response200: {Others200},"
            + "       Response403: {Others403},"
            + "       Response404: {Others404},"
            + "       Response4xx: {Others4xx},"
            + "       Response500: {Others500},"
            + "       Response503: {Others503},"
            # NonInternet
            + "\n"
            + "       NonInternet-Data-Get:  "
            + "\n"
            + "       Response200: {Get200NonInt},"
            + "       Response206: {Get206NonInt},"
            + "       Response403: {Get403NonInt},"
            + "       Response404: {Get404NonInt},"
            + "       Response4xx: {Get4xxNonInt},"
            + "       Response500: {Get500NonInt},"
            + "       Response503: {Get503NonInt},"
            + "\n"
            + "       NonInternet-Data-Head:  "
            + "\n"
            + "       Response200: {Head200NonInt},"
            + "       Response206: {Head206NonInt},"
            + "       Response403: {Head403NonInt},"
            + "       Response404: {Head404NonInt},"
            + "       Response4xx: {Head4xxNonInt},"
            + "       Response500: {Head500NonInt},"
            + "       Response503: {Head503NonInt},"
            + "\n"
            + "       NonInternet-Data-Put:  "
            + "\n"
            + "       Response200: {Put200NonInt},"
            + "       Response403: {Put403NonInt},"
            + "       Response404: {Put404NonInt},"
            + "       Response4xx: {Put4xxNonInt},"
            + "       Response500: {Put500NonInt},"
            + "       Response503: {Put503NonInt},"
            + "\n"
            + "       NonInternet-Data-Post:  "
            + "\n"
            + "       Response200: {Post200NonInt},"
            + "       Response403: {Post403NonInt},"
            + "       Response404: {Post404NonInt},"
            + "       Response4xx: {Post4xxNonInt},"
            + "       Response500: {Post500NonInt},"
            + "       Response503: {Post503NonInt},"
            + "\n"
            + "       NonInternet-Data-Delete:  "
            + "\n"
            + "       Response200: {Delete200NonInt},"
            + "       Response204: {Delete204NonInt},"
            + "       Response403: {Delete403NonInt},"
            + "       Response404: {Delete404NonInt},"
            + "       Response4xx: {Delete4xxNonInt},"
            + "       Response500: {Delete500NonInt},"
            + "       Response503: {Delete503NonInt},"
            + "\n"
            + "       NonInternet-Data-Others:  "
            + "\n"
            + "       Response200: {Others200NonInt},"
            + "       Response403: {Others403NonInt},"
            + "       Response404: {Others404NonInt},"
            + "       Response4xx: {Others4xxNonInt},"
            + "       Response500: {Others500NonInt},"
            + "       Response503: {Others503NonInt}"
    )

    RESPONSE_KEYS = ["Response200", "Response204", "Response206", "Response403", "Response404",
                     "Response4xx", "Response500", "Response503"]

    RETURN_CODE_KEYS = [
        'Get200', 'Get206', 'Get403', 'Get404', 'Get4xx', 'Get500', 'Get503',
        'Head200', 'Head206', 'Head403', 'Head404', 'Head4xx', 'Head500', 'Head503',
        'Put200', 'Put403', 'Put404', 'Put4xx', 'Put500', 'Put503',
        'Post200', 'Post403', 'Post404', 'Post4xx', 'Post500', 'Post503',
        'Delete200', 'Delete204', 'Delete403', 'Delete404', 'Delete4xx', 'Delete500', 'Delete503',
        'Others200', 'Others403', 'Others404', 'Others4xx', 'Others500', 'Others503',
        'Get200NonInt', 'Get206NonInt', 'Get403NonInt', 'Get404NonInt', 'Get4xxNonInt', 'Get500NonInt', 'Get503NonInt',
        'Head200NonInt', 'Head206NonInt', 'Head403NonInt', 'Head404NonInt', 'Head4xxNonInt', 'Head500NonInt',
        'Head503NonInt',
        'Put200NonInt', 'Put403NonInt', 'Put404NonInt', 'Put4xxNonInt', 'Put500NonInt', 'Put503NonInt',
        'Post200NonInt', 'Post403NonInt', 'Post404NonInt', 'Post4xxNonInt', 'Post500NonInt', 'Post503NonInt',
        'Delete200NonInt', 'Delete204NonInt', 'Delete403NonInt', 'Delete404NonInt', 'Delete4xxNonInt',
        'Delete500NonInt', 'Delete503NonInt',
        'Others200NonInt', 'Others403NonInt', 'Others404NonInt', 'Others4xxNonInt', 'Others500NonInt', 'Others503NonInt'
    ]

    def __init__(self, statistic, order):
        super().__init__()
        self.date = self.get_text(statistic, "Date")
        self.storage_class = self.get_response_storage(statistic)
        self.standard_data = self.get_data_code(statistic, "Data", self.RESPONSE_KEYS)
        self.standard_ia_data = self.get_data_code(statistic, "Standard_ia", self.RESPONSE_KEYS)
        self.msg = self.format_message(statistic, order)

    def format_message(self, statistic, order):
        storage_classes = {
            "ALL": ["Standard", "StandardIA"],
            "STANDARD": ["Standard"],
            "STANDARD_IA": ["StandardIA"]
        }
        message_parts = []
        for storage_class in storage_classes.get(self.storage_class):
            message_parts.append(self.OBJ_TEMPLATE.format(
                order=order,
                date=self.date,
                storage_class=storage_class,
                **self.select_data(storage_class, self.standard_data, self.standard_ia_data, self.RETURN_CODE_KEYS)
            ))
        return ''.join(message_parts)

    def to_string(self):
        return self.msg


class GetReturnCodeResult(Result):
    OBJ_TEMPLATE = (
            "Get ReturnCode Result: \n"
            + " Account: {Account}, "
            + " UserName: {UserName}, "
            + " TimeZone: {TimeZone}, "
            + " Freq: {Freq} "
            + " StorageClass: {StorageClass} "
            + " BucketName: {BucketName} "
            + " RegionName: {RegionName} "
            + " InternetType: {InternetType} "
            + " RequestsType: {RequestsType} "
            + " ResponseType: {ResponseType} "

            + " \n Statistics: {Statistics} "
    )

    Account = None
    UserName = None
    TimeZone = None
    Freq = None
    StorageClass = None
    BucketName = None
    RegionName = None
    InternetType = None
    RequestsType = None
    ResponseType = None

    Statistics = []
    xmlResp = ""
    msg = ""
    header = ResponseHeader()

    def set_header(self, header):
        self.header = header

    def get_header(self):
        return self.header

    def __init__(self):
        pass

    def parse(self, xml_response):
        xh = XMLHandler()
        xml.sax.parseString(xml_response, xh)
        self.xmlResp = xml_response
        result = xh.getDict()

        self.Account = result['Account']
        self.UserName = result['UserName']
        self.TimeZone = result['TimeZone']
        self.Freq = result['Freq']
        self.StorageClass = result['StorageClass']

        self.BucketName = result['BucketName']
        self.RegionName = result['RegionName']

        self.InternetType = result['InternetType']
        self.RequestsType = result['RequestsType']
        self.ResponseType = result['ResponseType']

        statistics_msg = ""

        statistics = parseString(xml_response).documentElement.getElementsByTagName("Statistics")
        ii = 0
        for xml_statistic in statistics:
            ii = ii + 1
            statistic = ReturnCodeStatistics(xml_statistic, ii)
            self.Statistics.append(statistic)
            statistics_msg += statistic.to_string()

        self.msg = self.OBJ_TEMPLATE.format(
            Account=self.Account,
            UserName=self.UserName,
            TimeZone=self.TimeZone,
            Freq=self.Freq,
            StorageClass=self.StorageClass,
            BucketName=self.BucketName,
            RegionName=self.RegionName,
            InternetType=self.InternetType,
            RequestsType=self.RequestsType,
            ResponseType=self.ResponseType,
            Statistics=statistics_msg,
        )

    def to_string(self):
        return self.msg

    def get_xml_resp(self):
        return self.xmlResp
