import pytest
from collections import namedtuple
from ixnetwork_restpy.testplatform.testplatform import TestPlatform
from ixnetwork_restpy import ConfigAssistant

def pytest_addoption(parser):
    parser.addoption('--server',default=[],action='append',help='''server: <server_ip>:<server_port>:<server_platform>
    example--> 
    --server 10.39.37.24:443:connection_manager 
    --server 10.117.156.155:443:linux
    --server 127.0.0.1:11009:windows
    ''')


def pytest_generate_tests(metafunc):
    if "server" in metafunc.fixturenames:
        metafunc.parametrize("server", metafunc.config.getoption("server"))


@pytest.fixture
def test_platform(server):
    # setup phase
    # 1.Connect
    # 2.Return Testplatform
    ip, port, platform = server.split(':')
    if platform == 'windows':
        test_platform = TestPlatform(ip, rest_port=port)
    else:
        test_platform = TestPlatform(ip)
    return test_platform


@pytest.fixture
def ixnetwork(test_platform):
    # setup phase
    # 1.connecting to server
    # 2.create test platform
    # 3.Add session in test platform
    # 4.get ixnetwork object
    # 5.exec new config
    # 6.returning an ixnetwork object
    # todo: implement for connection manager

    # creating server obj from test platform
    Server = namedtuple('Server', ['ip', 'port', 'platform'])
    server_obj = Server(
        test_platform.Hostname,
        test_platform.RestPort,
        test_platform.Platform
    )

    # authenticate regardless of platform
    # platforms that do not support authentication should treat it as a null operation    
    test_platform.Authenticate('admin', 'admin')

    # getting sessions as per test platform
    if test_platform.Platform == 'windows':
        session = test_platform.Sessions.find(Id=1)
    elif test_platform.Platform == 'linux':
        sessions = test_platform.Sessions.find()
        if (len(sessions) > 0) :
            session = sessions[0]
        else:
            session = test_platform.Sessions.add()
    elif test_platform.Platform == 'connection_manager':
        sessions = test_platform.Sessions.find()
        if (len(sessions) > 0) :
            session = sessions[0]
            if session.State != 'ACTIVE':
                session = test_platform.Sessions.add()    
        else:
            session = test_platform.Sessions.add()
            
    # getting ixnetwork object from session and return it
    ixnetwork = session.Ixnetwork
    ixnetwork.NewConfig()
    return ixnetwork

    # teardown phase
    #if server_obj.platform != 'windows':
    #    session.remove()

@pytest.fixture
def config_assistant(ixnetwork):
    return ConfigAssistant(ixnetwork)

@pytest.fixture
def vports(ixnetwork):
    # returns a couple of vports
    return ixnetwork.Vport.add(Name='ethernet-1').add(Name='ethernet-2')

@pytest.fixture
def ca_vports(config_assistant):
    # returns a couple of vports
    vport1, vport2 = config_assistant.config.Vport.add(Name='ethernet-1').add(Name='ethernet-2')
    return vport1, vport2, config_assistant

@pytest.fixture
def topologies(vports):
    vport_1, vport_2 = vports
    ixnetwork=vport_1._parent
    topology_1, topology_2 = ixnetwork.Topology.add(Vports=vport_1).add(Vports=vport_2)
    return topology_1, topology_2

@pytest.fixture
def ca_topologies(ca_vports):
    vport_1, vport_2 , config_assistant = ca_vports
    config = vport_1._parent
    topology_1, topology_2 = config.Topology.add(Vports=vport_1).add(Vports=vport_2)
    return topology_1, topology_2, config_assistant

@pytest.fixture
def device_groups(topologies):
    topology_1, topology_2 = topologies
    dg1 = topology_1.DeviceGroup.add()
    dg2 = topology_2.DeviceGroup.add()
    return dg1, dg2

@pytest.fixture
def ca_device_groups(ca_topologies):
    topology_1, topology_2, config_assistant = ca_topologies
    dg1 = topology_1.DeviceGroup.add()
    dg2 = topology_2.DeviceGroup.add()
    return dg1, dg2, config_assistant

@pytest.fixture
def ethernet_stacks(device_groups):
    dg1, dg2 = device_groups
    eth_1 = dg1.Ethernet.add()
    eth_2 = dg2.Ethernet.add()
    return eth_1, eth_2

@pytest.fixture
def ca_ethernet_stacks(ca_device_groups):
    dg1, dg2, config_assistant = ca_device_groups
    eth_1 = dg1.Ethernet.add()
    eth_2 = dg2.Ethernet.add()
    return eth_1, eth_2, config_assistant

@pytest.fixture
def ipv4_stacks(ethernet_stacks):
    eth_1, eth_2 = ethernet_stacks
    ipv4_1 = eth_1.Ipv4.add()
    ipv4_2 = eth_2.Ipv4.add()
    return ipv4_1, ipv4_2

@pytest.fixture
def ca_ipv4_stacks(ca_ethernet_stacks):
    eth_1, eth_2, config_assistant = ca_ethernet_stacks
    ipv4_1 = eth_1.Ipv4.add()
    ipv4_2 = eth_2.Ipv4.add()
    return ipv4_1, ipv4_2, config_assistant