#!/usr/bin/env python3

import os
import re
import json
from data import variables
from collections import OrderedDict

bmc_rec_pattern = '^=(.*)\n(.*)\n(.*)\n(.*)\n(.*)'
bmc_prop_pattern = [r"\w+", r"\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}", '443']
bmc_rec_prop = ['hostname', 'address', 'port', 'txt']


class Exception(Exception):
    def __init__(self, exc_value):
        self.exc_value = exc_value

    def __str__(self):
        return repr(self.exc_value)


def Check_bmc_record_exists(bmc_records, bmc_ip):
    r"""
    Parse the BMC records to check for passed input.

    Description of arguments:
    bmc_records            Contains the list of discoverd BMC records.
    bmc_ip                 BMC ip address.
    """

    try:
        for bmc_key, bmc_val in bmc_records.items():
            temp_ip = bmc_val.get('address', None)
            if bmc_ip.strip() == temp_ip.strip():
                return True
        else:
            return False
    except Exception as exc_obj:
        return exc_obj


def validate_bmc_properties(bmc_prop_pattern, bmc_prop, bmc_value,
                            bmc_rec_valid):
    r"""
    This function is to check pattern match in bmc properties.

    Description of arguments:
    bmc_prop_pattern       Regex pattern.
    bmc_prop               BMC property (e.g. hostname, address, port).
    bmc_value              BMC property value.
    bmc_rec_valid          Contain BMC properties record.
    """

    try:
        status = \
            [lambda bmc_prop: re.search(bmc_prop_pattern, bmc_prob),
                bmc_value]
        if None in status:
            bmc_rec_valid[bmc_prop] = None
    except Exception as exc_obj:
        return exc_obj
    finally:
        return bmc_rec_valid


def bmc_record_validation(bmc_rec_valid):
    r"""
    Parse the BMC records to validate the data is valid.

    Description of arguments:
    bmc_rec_valid          Contain BMC properties record.
    """

    try:
        for bmc_prop_key, bmc_pattern_val in \
                zip(bmc_rec_prop, bmc_prop_pattern):
            bmc_prop_value = bmc_rec_valid.get(bmc_prop_key, False)
            if bmc_rec_valid[bmc_prop_key] is not False:
                valid_status = validate_bmc_properties(bmc_pattern_val,
                                                       bmc_prop_key,
                                                       bmc_prop_value,
                                                       bmc_rec_valid)
                if None not in bmc_rec_valid.values():
                    return bmc_rec_valid
                else:
                    return None
    except Exception as exc_obj:
        return exc_obj


def bmc_inventory(service_type, bmc_inv_record):
    r"""
    Parse single record of BMC inventory and pack to dictionary form.

    Description of arguments:
    service_type       Service type (e.g. _obmc_rest._tcp, _obmc_redfish._tcp).
    bmc_inv_record     Individual BMC inventory record.

    This function will return this variable i.e.
    bmc_inv in dictionary form as mention below.

    Below are the discovered BMC detail.

    [service]:          _obmc_XXXX._tcp
    [hostname]:         System Name
    [address]:          XXX.XXX.XXX.XXX
    [port]:             XXX
    [txt]:
    """

    try:
        exc_obj = None
        bmc_inv = OrderedDict()
        service_count = 0
        for line in bmc_inv_record.split('\n'):
            if line == "":
                pass
            elif service_type in line:
                bmc_inv['service'] = service_type
                service_count += 1
            elif not line.startswith('=') and service_count == 1:
                bmc_inv[line.split('=')[0].strip()] = \
                    str(line.split('=')[-1].strip())[1:-1]
    except Exception as exc_obj:
        return exc_obj
    finally:
        valid_status = bmc_record_validation(bmc_inv)
        if valid_status is None:
            return None, exc_obj
        else:
            return valid_status, exc_obj


def get_bmc_records(service_type, bmc_records):
    r"""
    Parse the string to filter BMC discovery.

    Description of arguments:
    service_type     Service type (e.g. RESTService, RedfishService).
    bmc_records      Contains the list of discoverd BMC records.

    This function will return this variable i.e.
    bmc_inv_list in dictionary form as mention below.

    Below are the list of discovered BMC details.
    [1]:
        [service]:          _obmc_XXXX._tcp
        [hostname]:         System Name
        [address]:          XXX.XXX.XXX.XXX
        [port]:             XXX
        [txt]:
    [2]:
        [service]:          _obmc_XXXX._tcp
        [hostname]:         System Name
        [address]:          XXX.XXX.XXX.XXX
        [port]:             XXX
        [txt]:
    """

    try:
        count = 0
        exe_obj = None
        bmc_inv_list = OrderedDict()
        for match in re.finditer(bmc_rec_pattern, bmc_records,
                                 re.MULTILINE):
            bmc_record, exc_msg = \
                bmc_inventory(service_type, match.group())
            if bmc_record is not None and exc_msg is None:
                count += 1
                bmc_inv_list[count] = bmc_record
    except Exception as exe_obj:
        return exe_obj
    finally:
        if len(bmc_inv_list) == 0:
            '', exe_obj
        else:
            return bmc_inv_list, exe_obj