#!/usr/bin/env python

import requests
import json
import sys
from datetime import datetime
import csar_parser
import logging
import base64


class Preload:
    def __init__(self, vcpecommon):
        self.logger = logging.getLogger(__name__)
        self.logger.setLevel(logging.DEBUG)
        self.vcpecommon = vcpecommon

    def replace(self, sz, replace_dict):
        for old_string, new_string in replace_dict.items():
            sz = sz.replace(old_string, new_string)
        if self.vcpecommon.template_variable_symbol in sz:
            self.logger.error('Error! Cannot find a value to replace ' + sz)
        return sz

    def generate_json(self, template_file, replace_dict):
        with open(template_file) as json_input:
            json_data = json.load(json_input)
            stk = [json_data]
            while len(stk) > 0:
                data = stk.pop()
                for k, v in data.items():
                    if type(v) is dict:
                        stk.append(v)
                    elif type(v) is list:
                        stk.extend(v)
                    elif type(v) is str or type(v) is unicode:
                        if self.vcpecommon.template_variable_symbol in v:
                            data[k] = self.replace(v, replace_dict)
                    else:
                        self.logger.warning('Unexpected line in template: %s. Look for value %s', template_file, v)
        return json_data

    def reset_sniro(self):
        self.logger.debug('Clearing SNIRO data')
        r = requests.post(self.vcpecommon.sniro_url + '/reset', headers=self.vcpecommon.sniro_headers)
        if 2 != r.status_code / 100:
            self.logger.debug(r.content)
            self.logger.error('Clearing SNIRO date failed.')
            sys.exit(1)

    def preload_sniro(self, template_sniro_data, template_sniro_request, tunnelxconn_ar_name, vgw_name, vbrg_ar_name,
                      vgmux_svc_instance_uuid, vbrg_svc_instance_uuid):
        self.reset_sniro()
        self.logger.info('Preloading SNIRO for homing service')
        replace_dict = {'${tunnelxconn_ar_name}': tunnelxconn_ar_name,
                        '${vgw_name}': vgw_name,
                        '${brg_ar_name}': vbrg_ar_name,
                        '${vgmux_svc_instance_uuid}': vgmux_svc_instance_uuid,
                        '${vbrg_svc_instance_uuid}': vbrg_svc_instance_uuid
                        }
        sniro_data = self.generate_json(template_sniro_data, replace_dict)
        self.logger.debug('SNIRO data:')
        self.logger.debug(json.dumps(sniro_data, indent=4, sort_keys=True))

        base64_sniro_data = base64.b64encode(json.dumps(sniro_data))
        self.logger.debug('SNIRO data: 64')
        self.logger.debug(base64_sniro_data)
        replace_dict = {'${base64_sniro_data}': base64_sniro_data, '${sniro_ip}': self.vcpecommon.hosts['robot']}
        sniro_request = self.generate_json(template_sniro_request, replace_dict)
        self.logger.debug('SNIRO request:')
        self.logger.debug(json.dumps(sniro_request, indent=4, sort_keys=True))

        r = requests.post(self.vcpecommon.sniro_url, headers=self.vcpecommon.sniro_headers, json=sniro_request)
        if 2 != r.status_code / 100:
            response = r.json()
            self.logger.debug(json.dumps(response, indent=4, sort_keys=True))
            self.logger.error('SNIRO preloading failed.')
            sys.exit(1)

        return True

    def preload_network(self, template_file, network_role, subnet_start_ip, subnet_gateway, common_dict, name_suffix):
        """
        :param template_file:
        :param network_role: cpe_signal, cpe_public, brg_bng, bng_mux, mux_gw
        :param subnet_start_ip:
        :param subnet_gateway:
        :param name_suffix: e.g. '201711201311'
        :return:
        """
        network_name = '_'.join([self.vcpecommon.instance_name_prefix['network'], network_role.lower(), name_suffix])
        subnet_name = self.vcpecommon.network_name_to_subnet_name(network_name)
        common_dict['${' + network_role+'_net}'] = network_name
        common_dict['${' + network_role+'_subnet}'] = subnet_name
        replace_dict = {'${network_role}': network_role,
                        '${service_type}': 'vCPE',
                        '${network_type}': 'Generic NeutronNet',
                        '${network_name}': network_name,
                        '${subnet_start_ip}': subnet_start_ip,
                        '${subnet_gateway}': subnet_gateway
                        }
        self.logger.info('Preloading network ' + network_role)
        self.logger.info('template_file:' + template_file)
        if 'networkgra' in template_file:
              return self.preload(template_file, replace_dict, self.vcpecommon.sdnc_preload_network_gra_url)
        else:
              return self.preload(template_file, replace_dict, self.vcpecommon.sdnc_preload_network_url)

    def preload(self, template_file, replace_dict, url):
        self.logger.debug('tempalte_file:'+ template_file)
        json_data = self.generate_json(template_file, replace_dict)
        self.logger.debug(json.dumps(json_data, indent=4, sort_keys=True))
        r = requests.post(url, headers=self.vcpecommon.sdnc_headers, auth=self.vcpecommon.sdnc_userpass, json=json_data, verify=False)
        response = r.json()
        if int(response.get('output', {}).get('response-code', 0)) != 200:
            self.logger.debug(json.dumps(response, indent=4, sort_keys=True))
            self.logger.error('Preloading failed.')
            return False
        return True

    def preload_vgw(self, template_file, brg_mac, commont_dict, name_suffix):
        replace_dict = {'${brg_mac}': brg_mac,
                        '${suffix}': name_suffix
                        }
        replace_dict.update(commont_dict)
        self.logger.info('Preloading vGW')
        return self.preload(template_file, replace_dict, self.vcpecommon.sdnc_preload_vnf_url)

    def preload_vgw_gra(self, template_file, brg_mac, commont_dict, name_suffix, vgw_vfmod_name_index):
        replace_dict = {'${brg_mac}': brg_mac,
                        '${suffix}': name_suffix,
                        '${vgw_vfmod_name_index}': vgw_vfmod_name_index
                        }
        replace_dict.update(commont_dict)
        self.logger.info('Preloading vGW-GRA')
        return self.preload(template_file, replace_dict, self.vcpecommon.sdnc_preload_gra_url)

    def preload_vfmodule(self, template_file, service_instance_id, vnf_model, vfmodule_model, common_dict, name_suffix , gra_api_flag):
        """
        :param template_file:
        :param service_instance_id:
        :param vnf_model:  parsing results from csar_parser
        :param vfmodule_model:  parsing results from csar_parser
        :param common_dict:
        :param name_suffix:
        :return:
        """

        # examples:
        # vfmodule_model['modelCustomizationName']: "Vspinfra111601..base_vcpe_infra..module-0",
        # vnf_model['modelCustomizationName']: "vspinfra111601 0",

        vfmodule_name = '_'.join([self.vcpecommon.instance_name_prefix['vfmodule'],
                                  vfmodule_model['modelCustomizationName'].split('..')[0].lower(), name_suffix])

        # vnf_type and generic_vnf_type are identical
        replace_dict = {'${vnf_type}': vfmodule_model['modelCustomizationName'],
                        '${generic_vnf_type}': vfmodule_model['modelCustomizationName'],
                        '${service_type}': service_instance_id,
                        '${generic_vnf_name}': vnf_model['modelCustomizationName'],
                        '${vnf_name}': vfmodule_name,
                        '${mr_ip_addr}': self.vcpecommon.mr_ip_addr,
                        '${mr_ip_port}': self.vcpecommon.mr_ip_port,
                        '${sdnc_oam_ip}': self.vcpecommon.sdnc_oam_ip,
                        '${suffix}': name_suffix}
        replace_dict.update(common_dict)
        self.logger.info('Preloading VF Module ' + vfmodule_name)
	if  gra_api_flag:
             return self.preload(template_file, replace_dict, self.vcpecommon.sdnc_preload_gra_url)
        else:
             return self.preload(template_file, replace_dict, self.vcpecommon.sdnc_preload_vnf_url)

    def preload_all_networks(self, template_file, name_suffix):
        common_dict = {'${' + k + '}': v for k, v in self.vcpecommon.common_preload_config.items()}
        for network, v in self.vcpecommon.preload_network_config.items():
            subnet_start_ip, subnet_gateway_ip = v
            if not self.preload_network(template_file, network, subnet_start_ip, subnet_gateway_ip,
                                        common_dict, name_suffix):
                return None
        return common_dict

    def aai_region_query(self, req_method, json=None, verify=False):
        """
        Perform actual AAI API request for region
        :param req_method: request method ({'get','put'})
        :param json: Json payload
        :param verify: SSL verify mode
        :return:
        """
        url, headers, auth = (self.vcpecommon.aai_region_query_url,
                              self.vcpecommon.aai_headers,
                              self.vcpecommon.aai_userpass)
        try:
            if req_method == 'get':
                request = requests.get(url, headers=headers, auth=auth,
                                       verify=verify)
            elif req_method == 'put':
                request = requests.put(url, headers=headers, auth=auth,
                                        verify=verify, json=json)
            else:
                raise requests.exceptions.RequestException
        except requests.exceptions.RequestException as e:
            self.logger.error("Error connecting to AAI API. Error details: " + str(e.message))
            return False
        try:
            assert request.status_code == 200
        except AssertionError:
            self.logger.error('AAI request failed. API returned http code ' + str(request.status_code))
            return False
        try:
            return request.json()
        except ValueError as e:
            if req_method == 'get':
                self.logger.error('Unable to parse AAI response: ' + e.message)
                return False
            elif req_method == 'put':
                return request.ok
            else:
                return False

    def preload_aai_data(self, template_aai_region_data):
        """
        Update aai region data with identity-url
        :param template_aai_region_data: path to region data template
        :return:
        """
        request = self.aai_region_query('get')
        if request:
            # Check if identity-url already updated (for idempotency)
            self.logger.debug("Regiond data acquired from AAI:\n" + json.dumps(request,indent=4))
            try:
                assert request['identity-url']
            except KeyError:
                pass
            else:
                self.logger.info('Identity-url already present in {0} data, not updating'.format(self.vcpecommon.cloud['--os-region-name']))
                return

            # Get resource_version and relationship_list from region data
            resource_version = request['resource-version']
            relationship_list = request['relationship-list']

            replace_dict = {'${identity-url}': self.vcpecommon.cloud['--os-auth-url'],
                            '${identity_api_version}': self.vcpecommon.cloud['--os-identity-api-version'],
                            '${region_name}': self.vcpecommon.cloud['--os-region-name'],
                            '${resource_version}': resource_version
                           }
            json_data = self.generate_json(template_aai_region_data, replace_dict)
            json_data['relationship-list'] = relationship_list
            self.logger.debug('Region update payload:\n' + json.dumps(json_data,indent=4))
        else:
            sys.exit(1)

        # Update region data
        request = self.aai_region_query('put', json_data)
        if request:
            self.logger.info('Successully updated identity-url in {0} '
                    'region'.format(self.vcpecommon.cloud['--os-region-name']))
        else:
            sys.exit(1)

    def test(self):
        # this is for testing purpose
        name_suffix = datetime.now().strftime('%Y%m%d%H%M')
        preloader = Preload(self.vcpecommon)

        network_dict = {'${' + k + '}': v for k, v in self.vcpecommon.common_preload_config.items()}
        template_file = 'preload_templates/template.network.json'
        for k, v in self.vcpecommon.preload_network_config.items():
            if not preloader.preload_network(template_file, k, v[0], v[1], network_dict, name_suffix):
                break

        print('---------------------------------------------------------------')
        print('Network related replacement dictionary:')
        print(json.dumps(network_dict, indent=4, sort_keys=True))
        print('---------------------------------------------------------------')

        keys = ['infra', 'bng', 'gmux', 'brg']
        for key in keys:
            key_vnf= key + "_"
            key_gra = key + "gra_"
            csar_file = self.vcpecommon.find_file(key, 'csar', 'csar')
            template_file = self.vcpecommon.find_file(key_vnf, 'json', 'preload_templates')
            template_file_gra = self.vcpecommon.find_file(key_gra, 'json', 'preload_templates')
            if csar_file and template_file and template_file_gra:
                parser = csar_parser.CsarParser()
                parser.parse_csar(csar_file)
                service_instance_id = 'test112233'
 		# preload both VNF-API and GRA-API
                preloader.preload_vfmodule(template_file, service_instance_id, parser.vnf_models[0],
                                           parser.vfmodule_models[0], network_dict, name_suffix, False)
                preloader.preload_vfmodule(template_file_gra, service_instance_id, parser.vnf_models[0],
                                           parser.vfmodule_models[0], network_dict, name_suffix, True)


    def test_sniro(self):
        template_sniro_data = self.vcpecommon.find_file('sniro_data', 'json', 'preload_templates')
        template_sniro_request = self.vcpecommon.find_file('sniro_request', 'json', 'preload_templates')

        vcperescust_csar = self.vcpecommon.find_file('rescust', 'csar', 'csar')
        parser = csar_parser.CsarParser()
        parser.parse_csar(vcperescust_csar)
        tunnelxconn_ar_name = None
        brg_ar_name = None
        vgw_name = None
        for model in parser.vnf_models:
            if 'tunnel' in model['modelCustomizationName']:
                tunnelxconn_ar_name = model['modelCustomizationName']
            elif 'brg' in model['modelCustomizationName']:
                brg_ar_name = model['modelCustomizationName']
            elif 'vgw' in model['modelCustomizationName']:
                vgw_name = model['modelCustomizationName']

        if not (tunnelxconn_ar_name and brg_ar_name and vgw_name):
            self.logger.error('Cannot find all names from %s.', vcperescust_csar)
            sys.exit(1)

        vgmux_svc_instance_uuid = '88888888888888'
        vbrg_svc_instance_uuid = '999999999999999'

        self.preload_sniro(template_sniro_data, template_sniro_request, tunnelxconn_ar_name, vgw_name, brg_ar_name,
                           vgmux_svc_instance_uuid, vbrg_svc_instance_uuid)
