import jinja2
import six
import abc
import os

from ci_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)
