from networkapi.plugins.Cisco.NXOS.BGP.Cli import Generic
from networkapi.plugins.factory import PluginFactory
from mock import Mock
from mock import MagicMock
from random import randint
import os

from django.test import TestCase

class CliPluginTestCaseSuccess(TestCase):

    def setUp(self):

        self.ipv4_neighbor = {
            'remote_as': '200',
            'remote_ip': '172.16.31.10',
            'password': '<PASSWORD>',
            'maximum_hops': '5',
            'timer_keepalive': '3',
            'timer_timeout': '60',
            'description': 'desc',
            'soft_reconfiguration': True,
            'community': True,
            'remove_private_as': False,
            'next_hop_self': False
        }

        self.ipv6_neighbor = {
            'remote_as': '200',
            'remote_ip': 'fdac:3801:79b9:b96c:0:0:0:1',
            'password': '<PASSWORD>',
            'maximum_hops': '5',
            'timer_keepalive': '3',
            'timer_timeout': '60',
            'description': 'desc',
            'soft_reconfiguration': True,
            'community': True,
            'remove_private_as': False,
            'next_hop_self': False
        }

        self.asn = {'name': '25114'}
        self.vrf = {'vrf': 'Vrf-Test'}
        self.virtual_interface = {'name': 'VirtInt-Test'}

        self.fake_template_v4_path = 'networkapi/plugins/Cisco/NXOS/BGP/' \
                                     'tests/configs/config_v4_cisco'

        self.fake_template_v6_path = 'networkapi/plugins/Cisco/NXOS/BGP/' \
                                     'tests/configs/config_v6_cisco'

    def test_factory_bgp(self):
        equipment = self._mock_equipment()
        plugin = PluginFactory.factory(equipment)

        self.assertEqual(hasattr(plugin, 'bgp'), True)

    def test_factory_bgp_deploy_neighbor(self):
        equipment = self._mock_equipment()
        plugin = PluginFactory.factory(equipment)

        neighbor = {}

        self.assertEqual(hasattr(plugin.bgp(neighbor), 'deploy_neighbor'),
                         True)

    def test_factory_bgp_undeploy_neighbor(self):
        equipment = self._mock_equipment()
        plugin = PluginFactory.factory(equipment)

        neighbor = {}

        self.assertEqual(hasattr(plugin.bgp(neighbor), 'undeploy_neighbor'),
                         True)

    def test_generate_template_dict_for_ipv4_neighbor(self):

        plugin = Generic(equipment=self._mock_equipment(),
                         virtual_interface=self.virtual_interface,
                         neighbor=self.ipv4_neighbor, asn=self.asn,
                         vrf=self.vrf)

        returned_dict = plugin._generate_template_dict()

        expected_dict = {
            'AS_NUMBER': '25114',
            'VRF_NAME': 'Vrf-Test',
            'VIRTUAL_INTERFACE': 'VirtInt-Test',
            'REMOTE_IP': '172.16.31.10',
            'REMOTE_AS': '200',
            'PASSWORD': '<PASSWORD>',
            'TIMER_KEEPALIVE': '3',
            'TIMER_TIMEOUT': '60',
            'DESCRIPTION': 'desc',
            'SOFT_RECONFIGURATION': True,
            'COMMUNITY': True,
            'REMOVE_PRIVATE_AS': False,
            'NEXT_HOP_SELF': False
        }

        self.assertDictEqual(expected_dict, returned_dict)

    def test_get_deploy_template_name_for_ipv4_neighbor(self):

        self._helper_to_check_templates_name('deploy', self.ipv4_neighbor,
                                             'neighbor_v4_add')

    def test_get_deploy_template_name_for_ipv6_neighbor(self):

        self._helper_to_check_templates_name('deploy', self.ipv6_neighbor,
                                             'neighbor_v6_add')

    def test_get_undeploy_template_name_for_ipv4_neighbor(self):

        self._helper_to_check_templates_name('undeploy', self.ipv4_neighbor,
                                             'neighbor_v4_remove')

    def test_get_undeploy_template_name_for_ipv6_neighbor(self):

        self._helper_to_check_templates_name('undeploy', self.ipv6_neighbor,
                                             'neighbor_v6_remove')

    def test_generate_config_for_neighbor_v4_add(self):

        self._generate_config_helper('deploy', self.ipv4_neighbor,
                                     self.virtual_interface, self.asn, self.vrf,
                                     'template_neighbor_v4_add_cisco')

    def test_generate_config_for_neighbor_v6_add(self):

        self._generate_config_helper('deploy', self.ipv6_neighbor,
                                     self.virtual_interface, self.asn, self.vrf,
                                     'template_neighbor_v6_add_cisco')

    def test_generate_config_for_neighbor_v4_remove(self):

        self._generate_config_helper('undeploy', self.ipv4_neighbor,
                                     self.virtual_interface, self.asn, self.vrf,
                                     'template_neighbor_v4_remove_cisco')

    def test_generate_config_for_neighbor_v6_remove(self):

        self._generate_config_helper('undeploy', self.ipv6_neighbor,
                                     self.virtual_interface, self.asn, self.vrf,
                                     'template_neighbor_v6_remove_cisco')

    def _mock_equipment(self):

        equipment = Mock()
        marca = MagicMock(nome='CISCO')
        equipment.modelo = MagicMock(nome='NEXUS', marca=marca)
        equipment.maintenance = False
        equipment.id = randint(0,100000)

        return equipment

    def _mock_roteiro(self, roteiro):

        roteiro_str = MagicMock(roteiro=roteiro)
        roteiro_mock = MagicMock(roteiro=roteiro_str)

        return Mock(return_value=roteiro_mock)

    def _mock_plugin(self, plugin, roteiro):

        plugin.connect = MagicMock()
        plugin._ensure_privilege_level = MagicMock()
        plugin.close = MagicMock()
        plugin._copy_script_file_to_config = MagicMock()
        plugin._get_equipment_template = self._mock_roteiro(roteiro)

        return plugin

    def _helper_to_check_templates_name(self, type_operation, neighbor,
                                        expected_template_name):

        plugin = Generic(equipment=self._mock_equipment(),
                         virtual_interface=self.virtual_interface,
                         neighbor=neighbor, asn=self.asn,
                         vrf=self.vrf)

        if type_operation == 'deploy':
            returned_template_name = plugin._get_template_deploy_name()
        elif type_operation == 'undeploy':
            returned_template_name = plugin._get_template_undeploy_name()

        self.assertEquals(expected_template_name,
                          returned_template_name)

    def _generate_config_helper(self, type_operation, neighbor,
                                virtual_interface, asn, vrf, roteiro):

        plugin = Generic(equipment=self._mock_equipment(),
                         virtual_interface=virtual_interface,
                         neighbor=neighbor, asn=asn, vrf=vrf)
        plugin = self._mock_plugin(plugin, roteiro)

        if type_operation == 'deploy':
            template_name = plugin._get_template_deploy_name()
        elif type_operation == 'undeploy':
            template_name = plugin._get_template_undeploy_name()

        path_file_to_deploy = plugin._generate_config_file(template_name)

        if 'v4' in roteiro:
            fake_cisco = self._get_file_content(self.fake_template_v4_path,
                                                False)
        elif 'v6' in roteiro:
            fake_cisco = self._get_file_content(self.fake_template_v6_path,
                                                False)

        file_to_deploy = self._get_file_content(path_file_to_deploy, True)

        self.assertEquals(fake_cisco, file_to_deploy)

    def _get_file_content(self, path, delete_after):

        with open(path, 'r') as f:
            content = f.read()

        try:
            if delete_after:
                os.remove(path)
        except OSError:
            pass

        return content