##############################################################################
# Copyright 2018 EuropeanSoftwareMarketingLtd.
# ===================================================================
#  Licensed under the ApacheLicense, Version2.0 (the"License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#  http://www.apache.org/licenses/LICENSE-2.0
#
# software distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and limitations under
# the License
##############################################################################
# vnftest comment: this is a modified copy of
# yardstick/common/utils.py

import collections
import formatter
from contextlib import closing
import datetime
import errno
import importlib
from string import Formatter

import ipaddress
import logging
import os
import random
import socket
import subprocess
import sys

import pkg_resources
import six
from flask import jsonify
from six.moves import configparser
from oslo_serialization import jsonutils
import xml.etree.ElementTree
import vnftest

from vnftest.common.exceptions import ResourceNotFound

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

class_implementations = {}


# Decorator for cli-args
def cliargs(*args, **kwargs):
    def _decorator(func):
        func.__dict__.setdefault('arguments', []).insert(0, (args, kwargs))
        return func
    return _decorator


def findsubclasses(cls):
    if cls.__name__ not in class_implementations:
        # Load entrypoint classes just once.
        if len(class_implementations) == 0:
            for entrypoint in pkg_resources.iter_entry_points(group='vnftest.extension'):
                loaded_type = entrypoint.load()
                logger.info("Loaded: " + str(loaded_type))

        subclasses = []
        class_implementations[cls.__name__] = subclasses

        def getallnativesubclasses(clazz):
            for subclass in clazz.__subclasses__():
                subclasses.append(subclass)
                getallnativesubclasses(subclass)

        getallnativesubclasses(cls)
    return class_implementations[cls.__name__]


def import_modules_from_package(package):
    """Import modules given a package name

    :param: package - Full package name. For example: rally.deploy.engines
    """
    vnftest_root = os.path.dirname(os.path.dirname(vnftest.__file__))
    path = os.path.join(vnftest_root, *package.split('.'))
    for root, _, files in os.walk(path):
        matches = (filename for filename in files if filename.endswith('.py')
                   and not filename.startswith('__'))
        new_package = os.path.relpath(root, vnftest_root).replace(os.sep,
                                                                    '.')
        module_names = set(
            '{}.{}'.format(new_package, filename.rsplit('.py', 1)[0])
            for filename in matches)
        # Find modules which haven't already been imported
        missing_modules = module_names.difference(sys.modules)
        logger.debug('Importing modules: %s', missing_modules)
        for module_name in missing_modules:
            try:
                importlib.import_module(module_name)
            except (ImportError, SyntaxError):
                logger.exception('Unable to import module %s', module_name)


def makedirs(d):
    try:
        os.makedirs(d)
    except OSError as e:
        if e.errno != errno.EEXIST:
            raise


def remove_file(path):
    try:
        os.remove(path)
    except OSError as e:
        if e.errno != errno.ENOENT:
            raise


def execute_command(cmd):
    exec_msg = "Executing command: '%s'" % cmd
    logger.debug(exec_msg)

    output = subprocess.check_output(cmd.split()).split(os.linesep)

    return output


def source_env(env_file):
    p = subprocess.Popen(". %s; env" % env_file, stdout=subprocess.PIPE,
                         shell=True)
    output = p.communicate()[0]
    env = dict(line.split('=', 1) for line in output.splitlines() if '=' in line)
    os.environ.update(env)
    return env


def read_json_from_file(path):
    with open(path, 'r') as f:
        j = f.read()
    # don't use jsonutils.load() it conflicts with already decoded input
    return jsonutils.loads(j)


def write_json_to_file(path, data, mode='w'):
    with open(path, mode) as f:
        jsonutils.dump(data, f)


def write_file(path, data, mode='w'):
    with open(path, mode) as f:
        f.write(data)


def parse_ini_file(path):
    parser = configparser.ConfigParser()

    try:
        files = parser.read(path)
    except configparser.MissingSectionHeaderError:
        logger.exception('invalid file type')
        raise
    else:
        if not files:
            raise RuntimeError('file not exist')

    try:
        default = {k: v for k, v in parser.items('DEFAULT')}
    except configparser.NoSectionError:
        default = {}

    config = dict(DEFAULT=default,
                  **{s: {k: v for k, v in parser.items(
                      s)} for s in parser.sections()})

    return config


def get_port_mac(sshclient, port):
    cmd = "ifconfig |grep HWaddr |grep %s |awk '{print $5}' " % port
    status, stdout, stderr = sshclient.execute(cmd)

    if status:
        raise RuntimeError(stderr)
    return stdout.rstrip()


def get_port_ip(sshclient, port):
    cmd = "ifconfig %s |grep 'inet addr' |awk '{print $2}' " \
        "|cut -d ':' -f2 " % port
    status, stdout, stderr = sshclient.execute(cmd)

    if status:
        raise RuntimeError(stderr)
    return stdout.rstrip()


def flatten_dict_key(data):
    next_data = {}

    # use list, because iterable is too generic
    if not any(isinstance(v, (collections.Mapping, list))
               for v in data.values()):
        return data

    for k, v in data.items():
        if isinstance(v, collections.Mapping):
            for n_k, n_v in v.items():
                next_data["%s.%s" % (k, n_k)] = n_v
        # use list because iterable is too generic
        elif isinstance(v, collections.Iterable) and not isinstance(v, six.string_types):
            for index, item in enumerate(v):
                next_data["%s%d" % (k, index)] = item
        else:
            next_data[k] = v

    return flatten_dict_key(next_data)


def translate_to_str(obj):
    if isinstance(obj, collections.Mapping):
        return {str(k): translate_to_str(v) for k, v in obj.items()}
    elif isinstance(obj, list):
        return [translate_to_str(ele) for ele in obj]
    elif isinstance(obj, six.text_type):
        return str(obj)
    return obj


def result_handler(status, data):
    result = {
        'status': status,
        'result': data
    }
    return jsonify(result)


def change_obj_to_dict(obj):
    dic = {}
    for k, v in vars(obj).items():
        try:
            vars(v)
        except TypeError:
            dic.update({k: v})
    return dic


def set_dict_value(dic, keys, value):
    return_dic = dic

    for key in keys.split('.'):
        return_dic.setdefault(key, {})
        if key == keys.split('.')[-1]:
            return_dic[key] = value
        else:
            return_dic = return_dic[key]
    return dic


def get_free_port(ip):
    with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
        port = random.randint(5000, 10000)
        while s.connect_ex((ip, port)) == 0:
            port = random.randint(5000, 10000)
        return port


def mac_address_to_hex_list(mac):
    octets = ["0x{:02x}".format(int(elem, 16)) for elem in mac.split(':')]
    assert len(octets) == 6 and all(len(octet) == 4 for octet in octets)
    return octets


def safe_ip_address(ip_addr):
    """ get ip address version v6 or v4 """
    try:
        return ipaddress.ip_address(six.text_type(ip_addr))
    except ValueError:
        logging.error("%s is not valid", ip_addr)
        return None


def get_ip_version(ip_addr):
    """ get ip address version v6 or v4 """
    try:
        address = ipaddress.ip_address(six.text_type(ip_addr))
    except ValueError:
        logging.error("%s is not valid", ip_addr)
        return None
    else:
        return address.version


def ip_to_hex(ip_addr, separator=''):
    try:
        address = ipaddress.ip_address(six.text_type(ip_addr))
    except ValueError:
        logging.error("%s is not valid", ip_addr)
        return ip_addr

    if address.version != 4:
        return ip_addr

    if not separator:
        return '{:08x}'.format(int(address))

    return separator.join('{:02x}'.format(octet) for octet in address.packed)


def try_int(s, *args):
    """Convert to integer if possible."""
    try:
        return int(s)
    except (TypeError, ValueError):
        return args[0] if args else s


class SocketTopology(dict):

    @classmethod
    def parse_cpuinfo(cls, cpuinfo):
        socket_map = {}

        lines = cpuinfo.splitlines()

        core_details = []
        core_lines = {}
        for line in lines:
            if line.strip():
                name, value = line.split(":", 1)
                core_lines[name.strip()] = try_int(value.strip())
            else:
                core_details.append(core_lines)
                core_lines = {}

        for core in core_details:
            socket_map.setdefault(core["physical id"], {}).setdefault(
                core["core id"], {})[core["processor"]] = (
                core["processor"], core["core id"], core["physical id"])

        return cls(socket_map)

    def sockets(self):
        return sorted(self.keys())

    def cores(self):
        return sorted(core for cores in self.values() for core in cores)

    def processors(self):
        return sorted(
            proc for cores in self.values() for procs in cores.values() for
            proc in procs)


def config_to_dict(config):
    return {section: dict(config.items(section)) for section in
            config.sections()}


def validate_non_string_sequence(value, default=None, raise_exc=None):
    # NOTE(ralonsoh): refactor this function to check if raise_exc is an
    # Exception. Remove duplicate code, this function is duplicated in this
    # repository.
    if isinstance(value, collections.Sequence) and not isinstance(value, six.string_types):
        return value
    if raise_exc:
        raise raise_exc  # pylint: disable=raising-bad-type
    return default


def join_non_strings(separator, *non_strings):
    try:
        non_strings = validate_non_string_sequence(non_strings[0], raise_exc=RuntimeError)
    except (IndexError, RuntimeError):
        pass
    return str(separator).join(str(non_string) for non_string in non_strings)


def safe_decode_utf8(s):
    """Safe decode a str from UTF"""
    if six.PY3 and isinstance(s, bytes):
        return s.decode('utf-8', 'surrogateescape')
    return s


class ErrorClass(object):

    def __init__(self, *args, **kwargs):
        if 'test' not in kwargs:
            raise RuntimeError

    def __getattr__(self, item):
        raise AttributeError


class Timer(object):
    def __init__(self):
        super(Timer, self).__init__()
        self.start = self.delta = None

    def __enter__(self):
        self.start = datetime.datetime.now()
        return self

    def __exit__(self, *_):
        self.delta = datetime.datetime.now() - self.start

    def __getattr__(self, item):
        return getattr(self.delta, item)


def find_relative_file(path, task_path):
    """
    Find file in one of places: in abs of path or relative to a directory path,
    in this order.

    :param path:
    :param task_path:
    :return str: full path to file
    """
    # fixme: create schema to validate all fields have been provided
    for lookup in [os.path.abspath(path), os.path.join(task_path, path)]:
        try:
            with open(lookup):
                return lookup
        except IOError:
            pass
    raise IOError(errno.ENOENT, 'Unable to find {} file'.format(path))


def open_relative_file(path, task_path):
    try:
        return open(path)
    except IOError as e:
        if e.errno == errno.ENOENT:
            return open(os.path.join(task_path, path))
        raise


class dotdict(dict):
    """dot.notation access to dictionary attributes"""
    __getattr__ = dict.get
    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__


def normalize_data_struct(obj):
    if isinstance(obj, basestring):
        return [obj]
    if isinstance(obj, list):
        nomalized_list = []
        for element in obj:
            element = normalize_data_struct(element)
            nomalized_list.append(element)
        return nomalized_list
    if isinstance(obj, dict):
        normalized_dict = {}
        for k, v in obj:
            v = normalize_data_struct(v)
            normalized_dict[k] = v
        return normalized_dict
    return change_obj_to_dict(obj)


def xml_to_dict(xml_str):
    return element_tree_to_dict(xml.etree.ElementTree.fromstring(xml_str))


def element_tree_to_dict(element_tree):
    def internal_iter(tree, accum):
        if tree is None:
            return accum
        attribute_target = None
        if tree.getchildren():
            accum[tree.tag] = {}
            attribute_target = accum[tree.tag]
            for each in tree.getchildren():
                result = internal_iter(each, {})
                if each.tag in accum[tree.tag]:
                    if not isinstance(accum[tree.tag][each.tag], list):
                        accum[tree.tag][each.tag] = [
                            accum[tree.tag][each.tag]
                        ]
                    accum[tree.tag][each.tag].append(result[each.tag])
                else:
                    accum[tree.tag].update(result)
        else:
            attribute_target = accum
            accum[tree.tag] = tree.text
        # Add attributes
        attributes = tree.attrib or {}
        for att_name, att_value in attributes.iteritems():
            attribute_target[att_name] = att_value

        return accum

    return internal_iter(element_tree, {})


def resource_as_string(path):
    split_path = os.path.split(path)
    package = split_path[0].replace("/", ".")
    if not pkg_resources.resource_exists(package, split_path[1]):
        raise ResourceNotFound(resource=path)
    return pkg_resources.resource_string(package, split_path[1])


def load_resource(path):
    split_path = os.path.split(path)
    package = split_path[0].replace("/", ".")
    if not pkg_resources.resource_exists(package, split_path[1]):
        raise ResourceNotFound(resource=path)
    return pkg_resources.resource_stream(package, split_path[1])


def format(st, params):
    if not isinstance(st, basestring):
        return st
    ret_str = ""
    ret_obj = None
    for literal_text, field_name, format_spec, conversion in \
            Formatter().parse(st):
        if field_name is None:
            ret_str = ret_str + literal_text
        else:
            dict = ret_obj or params
            value = dict[field_name]
            if isinstance(value, basestring):
                ret_str = ret_str + value
            else:
                ret_obj = value
    return ret_obj or ret_str
