import os
import re
import subprocess

from cfg_checker.common.const import all_roles_map
from cfg_checker.common.exception import ConfigException

pkg_dir = os.path.dirname(__file__)
pkg_dir = os.path.join(pkg_dir, os.pardir, os.pardir)
pkg_dir = os.path.normpath(pkg_dir)
pkg_dir = os.path.abspath(pkg_dir)


def shell(command):
    _ps = subprocess.Popen(
        command.split(),
        stdout=subprocess.PIPE
    ).communicate()[0].decode()

    return _ps


class Utils(object):
    @staticmethod
    def validate_name(fqdn, message=False):
        """
        Function that tries to validate node name.
        Checks if code contains letters, has '.' in it,
        roles map contains code's role

        :param fqdn: node FQDN name to supply for the check
        :param message: True if validate should return error check message
        :return: False if checks failed, True if all checks passed
        """
        _message = "# Validation passed"

        def _result():
            return (True, _message) if message else True

        # node role code checks
        _code = re.findall("[a-zA-Z]+", fqdn.split('.')[0])
        if len(_code) > 0:
            if _code[0] in all_roles_map:
                return _result()
            else:
                # log warning here
                _message = "# Node code is unknown, '{}'. " \
                           "# Please, update map".format(_code)
        else:
            # log warning here
            _message = "# Node name is invalid, '{}'".format(fqdn)

        # put other checks here

        # output result
        return _result()

    @staticmethod
    def node_string_to_list(node_string):
        # supplied var should contain node list
        # if there is no ',' -> use space as a delimiter
        if node_string is not None:
            if node_string.find(',') < 0:
                return node_string.split(' ')
            else:
                return node_string.split(',')
        else:
            return []

    def get_node_code(self, fqdn):
        # validate
        _isvalid, _message = self.validate_name(fqdn, message=True)
        _code = re.findall("[a-zA-Z]+", fqdn.split('.')[0])
        # check if it is valid and raise if not
        if _isvalid:
            return _code[0]
        else:
            raise ConfigException(_message)

    def get_nodes_list(self, env, nodes_list):
        _list = []
        if env is None:
            # nothing supplied, use the one in repo
            try:
                if not nodes_list:
                    return []
                with open(os.path.join(pkg_dir, nodes_list)) as _f:
                    _list.extend(_f.read().splitlines())
            except IOError as e:
                raise ConfigException("# Error while loading file, '{}': "
                                      "{}".format(e.filename, e.strerror))
        else:
            _list.extend(self.node_string_to_list(env))

        # validate names
        _invalid = []
        _valid = []
        for idx in range(len(_list)):
            _name = _list[idx]
            if not self.validate_name(_name):
                _invalid.append(_name)
            else:
                _valid.append(_name)

        return _valid


utils = Utils()
