import operator
from copy import deepcopy
from device.proto.context_pb2 import DeviceDriverEnum, DeviceOperationalStatusEnum
from device.service.database.KpiSampleType import ORM_KpiSampleType
from .Tools import config_rule_set, config_rule_delete

# use "deepcopy" to prevent propagating forced changes during tests

DEVICE_EMU_UUID           = 'EMULATED'
DEVICE_EMU_TYPE           = 'emulated'
DEVICE_EMU_ADDRESS        = '127.0.0.1'
DEVICE_EMU_PORT           = '0'
DEVICE_EMU_DRIVERS        = [DeviceDriverEnum.DEVICEDRIVER_UNDEFINED]

DEVICE_EMU_ID = {'device_uuid': {'uuid': DEVICE_EMU_UUID}}
DEVICE_EMU = {
    'device_id': deepcopy(DEVICE_EMU_ID),
    'device_type': DEVICE_EMU_TYPE,
    'device_config': {'config_rules': []},
    'device_operational_status': DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_DISABLED,
    'device_drivers': DEVICE_EMU_DRIVERS,
    'device_endpoints': [],
}

PACKET_PORT_SAMPLE_TYPES = [
    ORM_KpiSampleType.PACKETS_TRANSMITTED,
    ORM_KpiSampleType.PACKETS_RECEIVED,
    ORM_KpiSampleType.BYTES_TRANSMITTED,
    ORM_KpiSampleType.BYTES_RECEIVED,
]

ENDPOINT_UUIDS = ['EP1', 'EP2', 'EP3', 'EP4']

DEVICE_EMU_ENDPOINTS = []
for endpoint_uuid in ENDPOINT_UUIDS:
    DEVICE_EMU_ENDPOINTS.append((endpoint_uuid, '10Gbps', PACKET_PORT_SAMPLE_TYPES))

RSRC_EP       = '/endpoints/endpoint[{:s}]'
RSRC_SUBIF    = RSRC_EP    + '/subinterfaces/subinterface[{:d}]'
RSRC_ADDRIPV4 = RSRC_SUBIF + '/ipv4/address[{:s}]'

DEVICE_EMU_ENDPOINTS_COOKED = []
for endpoint_uuid,endpoint_type,endpoint_sample_types in DEVICE_EMU_ENDPOINTS:
    endpoint_resource_key = RSRC_EP.format(str(endpoint_uuid))
    sample_types = {}
    for endpoint_sample_type in endpoint_sample_types:
        sample_type_name = endpoint_sample_type.name.lower()
        sample_types[endpoint_sample_type.value] = '{:s}/state/{:s}'.format(endpoint_resource_key, sample_type_name)
    endpoint_resource_value = {'uuid': endpoint_uuid, 'type': endpoint_type, 'sample_types': sample_types}
    DEVICE_EMU_ENDPOINTS_COOKED.append((endpoint_resource_key, endpoint_resource_value))

DEVICE_EMU_CONNECT_RULES = [
    config_rule_set('_connect/address',  DEVICE_EMU_ADDRESS ),
    config_rule_set('_connect/port',     DEVICE_EMU_PORT    ),
    config_rule_set('_connect/settings', {'endpoints': [
        {
            'uuid': endpoint_uuid, 'type': endpoint_type,
            'sample_types': list(map(operator.attrgetter('value'), endpoint_sample_types)),
        }
        for endpoint_uuid,endpoint_type,endpoint_sample_types in DEVICE_EMU_ENDPOINTS
    ]}),
]

DEVICE_EMU_CONFIG_ENDPOINTS = []
for endpoint_uuid in ENDPOINT_UUIDS:
    DEVICE_EMU_CONFIG_ENDPOINTS.append(config_rule_set(RSRC_EP.format(endpoint_uuid), {'enabled' : True}))

DEVICE_EMU_CONFIG_ADDRESSES = []
for endpoint_uuid in ENDPOINT_UUIDS:
    endpoint_number = int(endpoint_uuid.replace('EP', ''))
    subinterface_index = 0
    subinterface_address = '10.{:d}.{:d}.1'.format(endpoint_number, subinterface_index)
    subinterface_prefix_length = 24
    DEVICE_EMU_CONFIG_ADDRESSES.extend([
        config_rule_set(RSRC_SUBIF   .format(endpoint_uuid, subinterface_index), {
            'index': subinterface_index}),
        config_rule_set(RSRC_ADDRIPV4.format(endpoint_uuid, subinterface_index, subinterface_address), {
            'ip': subinterface_address, 'prefix_length': subinterface_prefix_length}),
    ])

DEVICE_EMU_RECONFIG_ADDRESSES = [
    config_rule_delete(RSRC_SUBIF   .format('EP2', 0            ), {}),
    config_rule_delete(RSRC_ADDRIPV4.format('EP2', 0, '10.2.0.1'), {'ip': '10.2.0.1', 'prefix_length': 24}),

    config_rule_set   (RSRC_SUBIF   .format('EP2', 1            ), {'index': 1}),
    config_rule_set   (RSRC_ADDRIPV4.format('EP2', 1, '10.2.1.1'), {'ip': '10.2.1.1', 'prefix_length': 24}),
]

DEVICE_EMU_DECONFIG_ADDRESSES = []
for endpoint_uuid in ENDPOINT_UUIDS:
    endpoint_number = int(endpoint_uuid.replace('EP', ''))
    subinterface_index = 1 if endpoint_uuid == 'EP2' else 0
    subinterface_address = '10.{:d}.{:d}.1'.format(endpoint_number, subinterface_index)
    DEVICE_EMU_DECONFIG_ADDRESSES.extend([
        config_rule_delete(RSRC_SUBIF   .format(endpoint_uuid, subinterface_index), {}),
        config_rule_delete(RSRC_ADDRIPV4.format(endpoint_uuid, subinterface_index, subinterface_address), {}),
    ])

DEVICE_EMU_DECONFIG_ENDPOINTS = []
for endpoint_uuid in ENDPOINT_UUIDS:
    DEVICE_EMU_DECONFIG_ENDPOINTS.append(config_rule_delete(RSRC_EP.format(endpoint_uuid), {}))
