from collections import namedtuple
from datetime import datetime

from .. import core
from parallels.core.utils.common import if_not_none
from parallels.core.utils.common.xml import elem, seq, text_elem

DomainInfo = namedtuple('DomainInfo', (
    'gen_info',
))

DomainGenInfo = namedtuple('DomainGenInfo', (
    'creation_date', 'name', 'ascii_name', 'status', 'real_size', 'dns_ip_address',
    'htype', 'guid',
))


class DomainOperator(object):
    class Dataset(object):
        GEN_INFO = 'gen_info'
        # Not implemented: 'hosting', 'limits', 'stat', 'prefs', 'user', 'disk_usage', 'performance'

        values = [GEN_INFO]
    
    FilterAll = core.FilterAll
    FilterByName = core.declare_filter('FilterByName', 'name')
    FilterByDomainName = core.declare_filter('FilterByName', 'domain-name')
    FilterByName8 = core.declare_filter('FilterByName8', 'domain_name')
    FilterById = core.declare_filter('FilterById', 'id')

    class Get(core.operation_with_filter('Get', ('dataset',))):
        operator_name = 'domain'
        operation_name = 'get'
        min_api_version = '1.4.1.2'
        max_api_version = None

        def data_xml(self):
            return [
                elem('dataset', [elem(value) for value in DomainOperator.Dataset.values if value in self.dataset])
            ]
            
        @classmethod
        def parse(cls, elem):
            return core.filter_owner_not_found_error(core.parse_result_set(elem, cls._parse_data, 'id'))
        
        @classmethod
        def _parse_data(cls, elem):
            domain_id = int(elem.findtext('id'))
            gen_info = cls._parse_gen_info(elem.find('data/gen_info'))
            
            return domain_id, DomainInfo(gen_info)
            
        @classmethod
        def _parse_gen_info(cls, elem):
            return DomainGenInfo(
                creation_date=datetime.strptime(elem.findtext('cr_date'), '%Y-%m-%d'),
                name=elem.findtext('name'), ascii_name=elem.findtext('ascii-name'),
                status=int(elem.findtext('status')), real_size=int(elem.findtext('real_size')),
                dns_ip_address=elem.findtext('dns_ip_address'),
                htype=elem.findtext('htype'), guid=elem.findtext('guid'),
            )

    DomainSetInfo = namedtuple('DomainSetInfo', ('user',))
    DomainSetUserInfo = namedtuple('DomainSetUserInfo', ('password',))

    class Set(core.operation_with_filter('Set', ('values',))):
        operator_name = 'domain'
        operation_name = 'set'
        min_api_version = '1.4.1.2'
        max_api_version = None

        def data_xml(self):
            return seq(
                elem('values', seq(
                    if_not_none(self.values.user, lambda ui: elem('user', [
                        if_not_none(ui.password, lambda p: text_elem('password', ui.password))
                    ]))
                ))
            )
        
        @classmethod
        def parse(cls, elem):
            return core.Result.parse(elem.find('result'))