import jinja2
import six
import abc
import os

from cfg_checker.common import const

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


def shortname(node_fqdn):
    # form shortname out of node fqdn
    return node_fqdn.split(".", 1)[0]


def is_equal(pkg_dict):
    # compare versions of given package
    return pkg_dict['installed'] == pkg_dict['candidate']


def is_active(node_dict):
    # check node status in node dict
    return node_dict['status'] == const.NODE_UP


def line_breaks(text):
    # replace python linebreaks with html breaks
    return text.replace("\n", "<br />")


@six.add_metaclass(abc.ABCMeta)
class _Base(object):
    def __init__(self):
        self.jinja2_env = self.init_jinja2_env()

    @abc.abstractmethod
    def __call__(self, payload):
        pass

    @staticmethod
    def init_jinja2_env():
        return jinja2.Environment(
            loader=jinja2.FileSystemLoader(os.path.join(pkg_dir, 'templates')),
            trim_blocks=True,
            lstrip_blocks=True)


class _TMPLBase(_Base):
    @abc.abstractproperty
    def tmpl(self):
        pass

    @staticmethod
    def _count_totals(data):
        data['counters']['total_nodes'] = len(data['nodes'])

    def __call__(self, payload):
        # init data structures
        data = self.common_data()
        data.update({
            "nodes": payload['nodes'],
            "diffs": payload['diffs']
        })

        # add template specific data
        self._extend_data(data)

        # do counts global
        self._count_totals(data)

        # specific filters
        self.jinja2_env.filters['shortname'] = shortname
        self.jinja2_env.filters['is_equal'] = is_equal
        self.jinja2_env.filters['is_active'] = is_active
        self.jinja2_env.filters['linebreaks'] = line_breaks

        # render!
        tmpl = self.jinja2_env.get_template(self.tmpl)
        return tmpl.render(data)

    def common_data(self):
        return {
            'counters': {},
            'salt_info': {}
        }

    def _extend_data(self, data):
        pass


# Package versions report
class HTMLPackageCandidates(_TMPLBase):
    tmpl = "pkg_versions_tmpl.j2"

    @staticmethod
    def is_fail_uniq(p_dict, p_name, nodes, node_name):
        # look up package fail for nodes with similar role
        _tgroup = nodes[node_name]['node_group']
        # filter all nodes with the same role
        _nodes_list = filter(
            lambda nd: nodes[nd]['node_group'] == _tgroup and nd != node_name,
            nodes
        )
        # lookup same package
        _fail_uniq = False
        for _node_name in _nodes_list:
            # check if there is a package present on node
            _nd = nodes[_node_name]['packages']
            if p_name not in _nd:
                continue
            # if both backages has same version and differ from candidate
            if p_dict['candidate'] == _nd[p_name]['candidate'] \
                    and _nd[p_name]['candidate'] == _nd[p_name]['installed']:
                # it is not uniq, mark and break
                _fail_uniq = True
        return _fail_uniq

    def _extend_data(self, data):
        _all_pkg = 0
        for key, value in data['nodes'].iteritems():
            # add count of packages for this node to total
            _all_pkg += len(value.keys())

            # count differences
            data['counters'][key] = {}
            data['counters'][key]['packages'] = len(value['packages'].keys())
            data['counters'][key]['package_diff'] = 0
            for pkg_name, pkg_value in value['packages'].iteritems():
                if pkg_value['installed'] != pkg_value['candidate']:
                    pkg_value['is_equal'] = False
                    pkg_value['fail_uniq'] = self.is_fail_uniq(
                        pkg_value,
                        pkg_name,
                        data['nodes'],
                        key
                    )
                    data['counters'][key]['package_diff'] += 1
                else:
                    pkg_value['is_equal'] = True
                    pkg_value['fail_uniq'] = False

        data['counters']['total_packages'] = _all_pkg


# Package versions report
class HTMLModelCompare(_TMPLBase):
    tmpl = "model_tree_cmp_tmpl.j2"

    def _extend_data(self, data):
        # move names into separate place
        data["names"] = data["diffs"].pop("diff_names")

        # counters - mdl_diff
        data['counters']['mdl_diff'] = len(data["diffs"].keys())


class ReportToFile(object):
    def __init__(self, report, target):
        self.report = report
        self.target = target

    def __call__(self, payload):
        payload = self.report(payload)

        if isinstance(self.target, six.string_types):
            self._wrapped_dump(payload)
        else:
            self._dump(payload, self.target)

    def _wrapped_dump(self, payload):
        with open(self.target, 'wt') as target:
            self._dump(payload, target)

    @staticmethod
    def _dump(payload, target):
        target.write(payload)
