from ifu_comlink_database.parser.ericsson import read_xls_file_site_info, read_xls_file_link_info

fn = '/Users/chwala-c/code/ifu_comlink_database/ifu_comlink_database/link_lists/Procema_2015_04_22.xlsx'

link_dict = read_xls_file_link_info(fn)
site_dict = read_xls_file_site_info(fn)

"""
Explanation: Requirements
In the case of Ericsson MINK LINK Traffic Node system one has to provide the following information to query data via SNMP:

IP adress
slot number
from which end to query, far_end or near_end

Read in link metadata (IP, slot, location, etc...) from XLS file
Below is a specific parser for the XLS files we get from Ericsson and 
will not be oh help for you since your may most likely get the 
metadata in a very different format. But I have to read our data
in to demostrate how to build the OID listing
Please note, that our metadata XLS file lists the slot information of 1+1 protection systems as e.g. '2+3', if slot 2 and 3 of a certain system (with the same IP) belong to the same 1+1 system. This is resolved in the functions below and two system are built for the SNMP requests. We later on put the back together when we process the raw data.
End of explanation
"""


for key in ['a_site', 'a_ip', 'a_slot', 'b_site', 'b_ip', 'b_slot']:
    print key, link_dict[key][0]

"""
Explanation: As an example the first link in the list
End of explanation
"""


def get_slot_list(slot_number_or_str):
    """
    Derive a list of slot numbers from XLS file entry
    
    Parameters
    ----------
    
    slot_number_or_str : int, float or unicode str
        Representation of slot or slots in XLS list. Unicode 
        string are used for the 1+1 protection systems.
        
    Returns
    -------
    
    slot_list : list
        List of slots. Even for only one slot a list is returned!   
    
    """
    
    if type(slot_number_or_str) == float:
        slot_list = [int(slot_number_or_str),]
    elif type(slot_number_or_str) == int:
        slot_list = [int(slot_number_or_str),]
    elif type(slot_number_or_str) == unicode:
        if slot_number_or_str == u'2+3 (1+1)':
            slot_list = [2,3]
        elif slot_number_or_str == u'3+4 (1+1)':
            slot_list = [3,4]
        elif slot_number_or_str == u'4+5 (1+1)':
            slot_list = [4,5]
        else:
            raise ValueError('slot_number_of_string string not understood')
    else:
        raise ValueError('slot_number_of_string must be int, float or unicode')
    return slot_list

"""
Explanation: Functions to build link OID dict list
Function to derive slots from entry in link_dict
End of explanation
"""


def build_TN_interface_descriptor(slot, near_far):
    """ 
    Calculate the interface descriptor for TN MW links
    
    Parameters
    ----------
    
    slot : int
        Slot number
    near_far : str
        String to indicate which end of the link is the aim.
        Options are: `near`, `far` and `far_protect`
    
    Returns
    -------
    
    str
        String of interface descriptor, e.g. 
        2146697601 for slot 3 at near_end
        
    """
    
    # This are the values for slot 2, that do not have to be altered
    if near_far=='near':
        hex_base = '0x7ff40101'
    elif near_far=='far':
        hex_base = '0x7ef40101'
    elif near_far=='far_protect':
        hex_base = '0x7df40101'
    else:
        raise ValueError("near_far can only be 'near', 'far' or 'far_protect'")
    # Add 128 for each slot greater than 2 and return as string of an int
    return str(int(hex_base,16) + 128*(int(slot)-2))

def build_TN_OID(cmd, slot, near_far):
    """
    Build OIDs from a certain SNMP query command
    
       Parameters
    ----------
    
    cmd : str
        Command for SNMP request. Right now only `RX` and `TX` are supported
    slot : int
        Slot number
      near_far : str
        String to indicate which end of the link is the aim.
        Options are: `near`, `far` and `far_protect`
            
    Returns
    -------
    
    str
        OID as a string starting with a `.`, e.g. 
        .1.3.6.1.4.1.193.81.3.4.3.1.3.1.10.2146697601
        for `RX` level at slot 3 at near_end
    
    """
    
    OIDS = {}
    OIDS['TX'] = '.1.3.6.1.4.1.193.81.3.4.3.1.3.1.1'
    OIDS['RX'] = '.1.3.6.1.4.1.193.81.3.4.3.1.3.1.10'
    # Return OID plus interface_descriptor for slot and near or far end
    return OIDS[cmd] + '.' + build_TN_interface_descriptor(slot, near_far)

"""
Explanation: Functions for building the correct OIDs for Ericsson MiniLink TN
End of explanation
"""


print int(build_TN_interface_descriptor(2, 'near'))
print int(build_TN_interface_descriptor(3, 'near'))
print int(build_TN_interface_descriptor(4, 'near'))

print hex(int(build_TN_interface_descriptor(2, 'near')))
print hex(int(build_TN_interface_descriptor(3, 'near')))
print hex(int(build_TN_interface_descriptor(4, 'near')))

print bin(int(build_TN_interface_descriptor(2, 'near')))
print bin(int(build_TN_interface_descriptor(3, 'near')))
print bin(int(build_TN_interface_descriptor(4, 'near')))

"""
Explanation: Test the function for building the interface desciptor
End of explanation
"""


for slot in range(2,6):
    print ''
    for nf in ['near', 'far', 'far_protect']:
        print slot, nf, build_TN_OID('RX', slot, nf)

"""
Explanation: Test the function to build OID
End of explanation
"""


link_list = []
OID_list = ['TX', 'RX']

for i in range(len(link_dict['a_slot'])):
    # Get ID, Slots and IP
    a_id = link_dict['a_site'][i]
    b_id = link_dict['b_site'][i]
    a_slot_list = get_slot_list(link_dict['a_slot'][i])
    b_slot_list = get_slot_list(link_dict['b_slot'][i])
    ip = link_dict['a_ip'][i]
    
    # Check if near end uses a 1+1 protection (i.e. two slots are used) 
    if len(a_slot_list) == 1:
        protection_near = False
    elif len(a_slot_list) == 2:
        protection_near = True
    else:
        raise ValueError('There should only be 1 or 2 slots for site A')
    # Check if far end uses 1+1 protection
    if len(b_slot_list) == 1:
        protection_far = False
    elif len(b_slot_list) == 2:
        protection_far = True
    else:
        raise ValueError('There should only be 1 or 2 slots for site B')
        
    # Build OID dict and append to link_list together with metadata
    for a_slot in a_slot_list:
        for i_b_slot, b_slot in enumerate(b_slot_list):
            link_id = a_id + '_' + str(a_slot) + '_' + b_id + '_' + str(b_slot)
            OID_dict = {}
            # Build OID dict and distinguish between far end with and without 1+1 protection.
            # (This is not necessary for near end.)
            for far_near in ['far', 'near']:
                # Adjust OID for far end protection
                for OID in OID_list:
                    if i_b_slot == 0:
                        TN_OID = build_TN_OID(OID, a_slot, far_near)
                    elif i_b_slot == 1 and far_near == 'near':
                        TN_OID = build_TN_OID(OID, a_slot, 'near')
                    elif i_b_slot == 1 and far_near == 'far':
                        TN_OID = build_TN_OID(OID, a_slot, 'far_protect')
                    else:
                        raise ValueError('There seem to be more than two \
                                         slots for far end. This is not supported.')
                    OID_dict[OID + '_' + far_near] = TN_OID
            # Append to link_list
            link_list.append({'ID': link_id,
                              'IP' : ip,
                              'protection_near': protection_near,
                              'protection_far': protection_far,
                              'slot_near': a_slot,
                              'slot_far': b_slot,
                              'OID_dict': OID_dict})

"""
Explanation: Build a OID dict list to query RX- and TX-levels from far_end and near_end
The format (list of dictonaries with the specific keys) is the the format pySNMPdaq expects
End of explanation
"""


link_list[0:3]

"""
Explanation: Show the first entries of the OID dict list
End of explanation
"""


import pprint

f = open('link_list.py','w')
pprint.pprint(link_list, f)
f.close()

"""
Explanation: Dump the OID dict list to a file so that pySNMPdaq can read it in
End of explanation
"""


