import xml.etree.cElementTree as ET
import os
import pathlib
import re

cucm_version = '14.0'

cwd = os.path.dirname(os.path.abspath(__file__))
xsd = pathlib.PurePosixPath(f"{cwd}/schema/{cucm_version}/AXLSoap.xsd")

def camel_to_snake(name):
    s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
    return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()


def create_def_get(name, returned):
    rec = f'''
    def {name.replace("Get", "")}(self, **args):
        """
        axl.get.{name} parameters
        :param name: name
        :param uuid: uuid 
        :return: result dictionary
        """
        try:
            resp = self.client.get{name[3:]}(**args)
            if resp['return']:
                soap_result = serialize_object(resp['return'], dict)['{returned}']
                if soap_result is None:
                    return []
                elif isinstance(soap_result, dict):
                    return [soap_result]
                elif isinstance(soap_result, list):
                    return soap_result
                else:
                    return [soap_result]
            return True

        except Fault as err:
            print(f"AXL error get{name[3:]}: ", str(err), file=sys.stderr)
            return False
        '''

    with open('Get/Get.py', 'a') as filehandle:
        filehandle.write(rec)
        filehandle.write('\n')
        filehandle.close()

tree = ET.ElementTree(file=xsd)
root = tree.getroot()

def parse_get(child):
    for sub in child:
        if 'complexContent' in sub.tag:
            for a in sub:
                if 'extension' in a.tag:
                    for b in a:
                        if 'sequence' in b.tag:
                            for c in b:
                                if 'element' in c.tag:
                                    for d in c:
                                        if 'complexType' in d.tag:
                                            for e in d:
                                                if 'sequence' in e.tag:
                                                    for f in e:
                                                        if 'element' in f.tag:
                                                            create_def_get(child.attrib['name'].split('Res')[0], f.attrib['name'])

def create_params(reqs):
    res = ''
    for each in reqs:
        res = res+':param '+each.attrib['name']+': '+each.attrib['name']+'\n'
    return res+':return: result list of dictionaries'

def create_params_new(reqs):
    res = ''
    for each in reqs:
        res = res+':param '+each+': '+each+'\n\t'
    return res+':return: API Response message'

def create_def_list(name, params, returning):
    # print(name)
    # print(reqs)
    # params = create_params(reqs)
    rec = f'''
    def {name[4:]}(self, name=''):
        """
        {camel_to_snake(name)} parameters
        :param uuid: uuid
        {params}
        """
        try:
            resp = self.client.list{name[4:]}(
                {{'name': '%'+name}}, returnedTags={returning}
            )
            if resp['return']:
                soap_result = serialize_object(resp['return'], dict)['{get_res_from_req(name)}']
                if soap_result is None:
                    return []
                elif isinstance(soap_result, dict):
                    return [soap_result]
                elif isinstance(soap_result, list):
                    return soap_result
                else:
                    return [soap_result]
            return True

        except Fault as err:
            print(f"AXL error list{name[4:]}: ", str(err), file=sys.stderr)
            return False
        '''
    with open('List/List.py', 'a') as filehandle:
        filehandle.write(rec)
        filehandle.write('\n')
        filehandle.close()

def find_return(child):
    for sub in child:
        if 'complexContent' in sub.tag:
            for a in sub:
                if 'extension' in a.tag:
                    for b in a:
                        if 'sequence' in b.tag:
                            for c in b:
                                if 'element' in c.tag:
                                    for d in c:
                                        if 'complexType' in d.tag:
                                            for e in d:
                                                if 'sequence' in e.tag:
                                                    for f in e:
                                                        if 'element' in f.tag:
                                                            #print(f.attrib['name'])
                                                            return f.attrib['name']
                                        #create_def_list(child.attrib['name'].split('Req')[0], c)
def get_res_from_req(req):
    for child in root:
        if 'complexType' in child.tag:
        # if 'Get' in child.attrib['name'][:3] and 'Res' in child.attrib['name']:
        #     parse_get(child)
        # if 'Remove' in child.attrib['name'][:6] and 'Req' in child.attrib['name']:
        #     parse_remove(child)

            if req in child.attrib['name'][:-3] and 'Res' in child.attrib['name']:
                return find_return(child)

def create_def_update(child, reqs):
    params = create_params_new(reqs)
    rec = f'''
    def {child.replace("Update", "")}(self, **args):
        """
        {child} parameters
        {params}
        """
        try:
            resp = self.client.update{child[6:]}(**args)
            if resp['return']:
                soap_result = serialize_object(resp['return'], dict)['return']
                if soap_result is None:
                    return []
                elif isinstance(soap_result, dict):
                    return [soap_result]
                elif isinstance(soap_result, list):
                    return soap_result
                else:
                    return [soap_result]
            return True
    
        except Fault as err:
            print(f"AXL error update{child[6:]}: ", str(err), file=sys.stderr)
            return False
    '''
    with open("Update/Update.py", 'a') as filehandle:
        filehandle.write(rec)
        filehandle.write('\n')
        filehandle.close()


def create_def_add(child, reqs):
    params = create_params_new(reqs)
    rec = f'''
    def {child.replace("Add", "")}(self, **args):
        """
        {child.replace("Add", "")} parameters
        {params}
        """
        result = {{
            'success': False,
            'response': '',
            'error': '',
        }}
        try:
            resp = self.client.add{child[3:]}(**args)
            if resp['return']:
                soap_result = serialize_object(resp['return'], dict)['return']
                if soap_result is None:
                    return []
                elif isinstance(soap_result, dict):
                    return [soap_result]
                elif isinstance(soap_result, list):
                    return soap_result
                else:
                    return [soap_result]
            return True
    
        except Fault as err:
            print(f"AXL error add{child[3:]}: ", str(err), file=sys.stderr)
            return False
        '''

    with open('Add/Add.py', 'a') as filehandle:
        filehandle.write(rec)
        filehandle.write('\n')
        filehandle.close()


def create_def_remove(child, reqs):
    params = create_params(reqs)
    rec = f'''
    def {child.replace("Remove", "")}(self, **args):
        """
        {child.replace("Remove", "")} parameters
        :param uuid: uuid
        {params}
        """
        try:
            resp = self.client.remove{child[6:]}(**args)
            if resp['return']:
                soap_result = serialize_object(resp['return'], dict)['return']
                if soap_result is None:
                    return []
                elif isinstance(soap_result, dict):
                    return [soap_result]
                elif isinstance(soap_result, list):
                    return soap_result
                else:
                    return [soap_result]
            return True

        except Fault as err:
            print(f"AXL error remove{child[6:]}: ", str(err), file=sys.stderr)
            return False
    '''

    with open('Remove/Remove.py', 'a') as filehandle:
        filehandle.write(rec)
        filehandle.write('\n')
        filehandle.close()

def create_def_do(child, reqs):
    params = create_params(reqs)
    rec = f'''
    def {child.replace("Do", "")}(self, **args):
        """
        {child.replace("Do", "")} parameters
        :param uuid: uuid
        {params}
        """
        try:
            resp = self.client.do{child[2:]}(**args)
            if resp['return']:
                soap_result = serialize_object(resp['return'], dict)['return']
                if soap_result is None:
                    return []
                elif isinstance(soap_result, dict):
                    return [soap_result]
                elif isinstance(soap_result, list):
                    return soap_result
                else:
                    return [soap_result]
            return True
    
        except Fault as err:
            print(f"AXL error remove{do[2:]}: ", str(err), file=sys.stderr)
            return False
    '''

    with open('Do/Do.py', 'a') as filehandle:
        filehandle.write(rec)
        filehandle.write('\n')
        filehandle.close()

def get_res(name):
    returned={}
    for child in root:
        if 'complexType' in child.tag:
            if 'L'+name[4:] in child.attrib['name']:
                for sub in child:
                    if 'sequence' in sub.tag:
                        for a in sub:
                            if 'element' in a.tag:
                                returned[a.attrib['name']] = ''
    return returned

def get_add_params(name):
    returned=[]
    for child in root:
        if 'complexType' in child.tag:
            if name in child.attrib['name']:
                for sub in child:
                    if 'sequence' in sub.tag:
                        for a in sub:
                            if 'element' in a.tag:
                                returned.append(a.attrib['name'])
    return returned

            #print(child.attrib) 
            # and 'L'+name[4:] in child.attrib:
            # print(child)
            # for sub in child:
            #     print(sub)
            #     if sub.attrib['name'] is 'L'+name[4:]:
            #         print(sub)
def parse_list(child):
    #print(child.attrib['name'].split('Req')[0])
    params = ''
    req_params = ''
    for sub in child:
        if 'sequence' in sub.tag:
            for a in sub:
                if 'element' in a.tag:
                    for b in a:
                        if 'complexType' in b.tag:
                            for c in b:
                                if 'sequence' in c.tag:
                                    for d in c:
                                        if 'element' in d.tag:
                                            # print(d.attrib['name'])
                                            # for each in d:
                                            #     print(each)
                                            params = params+':param '+d.attrib['name']+': '+d.attrib['name']+'\n\t\t'
    returning = get_res(child.attrib['name'].split('Req')[0])
    create_def_list(child.attrib['name'].split('Req')[0], params.strip(), returning)
    #print(child.attrib['name'].split('Req')[0],'\n',res)
                                #return res+':return: result list of dictionaries'
                                #create_def_list(child.attrib['name'].split('Req')[0], res)
                                        #if 'element' in d.tag:
                                            
                                            #print(d.attrib['name'])
                                                #print(e.attrib['name'])
                                        #print(d)
                                    #print(c.attrib['name'])
                            #create_def_remove(child.attrib['name'].split('Req')[0], b)

def parse_add(child):
    for sub in child:
        if 'complexContent' in sub.tag:
            for a in sub:
                if 'extension' in a.tag:
                    for b in a:
                        if 'sequence' in b.tag:
                            for c in b:
                                if 'element' in c.tag:
                                    elem_type = c.attrib['type'].split('axlapi:')[1]
                                    #elem_name = c.attrib['name']
                                    add_params = get_add_params(elem_type)
                                    create_def_add(child.attrib['name'].split('Req')[0], add_params)

def parse_do(child):
    for sub in child:
        if 'complexContent' in sub.tag:
            for a in sub:
                if 'extension' in a.tag:
                    for b in a:
                        if 'sequence' in b.tag:
                            for c in b:
                                if 'element' in c.tag:
                                    elem_type = c.attrib['type'].split('axlapi:')[1]
                                    # elem_name = c.attrib['name']
                                    add_params = get_add_params(elem_type)
                                    create_def_add(
                                        child.attrib['name'].split('Req')[0],
                                        add_params)

def parse_update(child):
    update_params = []
    for sub in child:
        if 'complexContent' in sub.tag:
            for a in sub:
                if 'extension' in a.tag:
                    for b in a:
                        if 'sequence' in b.tag:
                            for c in b:
                                if 'element' in c.tag:
                                    print(c.attrib['name'])
                                    #elem_type = c.attrib['type'].split('axlapi:')[1]
                                    #elem_name = c.attrib['name']
                                    update_params.append(c.attrib['name'])
    create_def_update(child.attrib['name'].split('Req')[0], update_params)

def parse_remove(child):
    for sub in child:
        if 'sequence' in sub.tag:
            for a in sub:
                if 'choice' in a.tag:
                    for b in a:
                        if 'sequence' in b.tag:
                            create_def_remove(child.attrib['name'].split('Req')[0], b)
                    #         for c in b:
                    #             print(c.attrib['name'])
                    #     #print(b.attrib['name'])
                    # #print(a.attrib['base'])
                    # if a.attrib['base'] is 'axlapi:StandardResponse':
                    #     print(child.attrib['name'].split('Res')[0])
                    # else:
                    #     for b in a:
                    #         if 'sequence' in b.tag:
                    #             for c in b:
                    #                 if 'element' in c.tag:
                    #                     for d in c:
                    #                         if 'complexType' in d.tag:
                    #                             for e in d:
                    #                                 if 'sequence' in e.tag:
                    #                                     for f in e:
                    #                                         print(child.attrib['name'].split('Res')[0])
                    #                                         print(f.attrib)
                    #                                         #if 'element' in f.tag:
                    #                                             #create_def_do_complex(camel_to_snake(child.attrib['name'].split('Res')[0]), f.attrib['name'])
                    #                         elif 'simpleType' in d.tag:
                    #                             for e in d:
                    #                                 print(child.attrib['name'].split('Res')[0])
                    #                                 print(e.attrib)
                    #                                 #create_def_do_simple(camel_to_snake(child.attrib['name'].split('Res')[0]))

for child in root:
    if 'complexType' in child.tag:
        if 'Get' in child.attrib['name'][:3] and 'Res' in child.attrib['name']:
            parse_get(child)
        if 'Remove' in child.attrib['name'][:6] and 'Req' in child.attrib['name']:
            parse_remove(child)
        if 'List' in child.attrib['name'][:4] and 'Req' in child.attrib['name']:
            parse_list(child)
        if 'Add' in child.attrib['name'][:3] and 'Req' in child.attrib['name']:
            parse_add(child)
        if 'Update' in child.attrib['name'][:6] and 'Req' in child.attrib['name']:
            parse_update(child)
        if 'Do' in child.attrib['name'][:2] and 'Req' in child.attrib['name']:
            parse_update(child)