'''
 rmtoo
   Free and Open Source Requirements Management Tool

 tlp1 output class.

 (c) 2011-2012,2017 by flonatel

 For licensing details see COPYING
'''

from rmtoo.lib.logging import tracer
from rmtoo.lib.StdOutputParams import StdOutputParams
from rmtoo.lib.ExecutorTopicContinuum import ExecutorTopicContinuum
from rmtoo.lib.CreateMakeDependencies import CreateMakeDependencies


class Tlp1(StdOutputParams, ExecutorTopicContinuum,
           CreateMakeDependencies):
    """Write tulip compatible output"""

    # pylint: disable=too-few-public-methods
    class Id2IntMapper(object):
        """Maps rmtoo-ids to (tuplip) ints"""

        def __init__(self):
            self.next_int = 0
            self.mappings = {}
            self.imapping = {}

        def get(self, req_id):
            """Get the mapping for req_id

            If not already available, create a new.
            """
            if req_id in self.mappings:
                return self.mappings[req_id]
            next_idx = self.next_int
            self.mappings[req_id] = next_idx
            self.imapping[next_idx] = req_id
            self.next_int += 1
            return next_idx

    def __init__(self, oconfig):
        '''Create a graph output object.'''
        tracer.debug("Called.")
        StdOutputParams.__init__(self, oconfig)
        CreateMakeDependencies.__init__(self)

    def topic_continuum_sort(self, vcs_commit_ids, topic_sets):
        '''Because tlp1 can only one topic continuum,
           the latest (newest) is used.'''
        return [topic_sets[vcs_commit_ids[-1].get_commit()]]

    def requirement_set_pre(self, requirement_set):
        '''This is called in the RequirementSet pre-phase.'''
        with open(self._output_filename, "w") as out_fd:
            reqs_count = requirement_set.get_requirements_cnt()
            i2im = Tlp1.Id2IntMapper()
            self.write_header(out_fd)
            self.write_node_ids(out_fd, reqs_count)
            self.write_edges(out_fd, requirement_set, i2im)
            self.write_labels(out_fd, i2im)
            self.write_footer(out_fd)

    @staticmethod
    def write_header(out_fd):
        """Write the TLP header"""
        out_fd.write('(tlp "2.0"\n')
        # ToDO: very complicated to check this during tests.
        # fd.write('(date "%s")\n' % time.strftime("%d-%m-%Y"))
        out_fd.write('(comments "This file was generated by rmtoo.")\n')

    @staticmethod
    def write_node_ids(out_fd, max_cnt):
        """Write out all the node ids"""
        out_fd.write("(nodes ")
        for i in range(0, max_cnt):
            out_fd.write("%d " % i)
        out_fd.write(")\n")

    @staticmethod
    def write_edges(out_fd, reqset, i2im):
        """Write out all the edges"""
        e_cnt = 0
        for rid in sorted(reqset.get_all_requirement_ids()):
            req = reqset.get_requirement(rid)
            e_idx = i2im.get(req.get_id())
            for in_name in sorted(req.incoming, key=lambda t: t.name):
                e_jdx = i2im.get(in_name.get_id())
                out_fd.write("(edge %d %d %d)\n" % (e_cnt, e_idx, e_jdx))
                e_cnt += 1

    @staticmethod
    def write_labels(out_fd, i2im):
        """Write out the labels of the nodes"""
        out_fd.write('(property  0 string "viewLabel"\n')
        out_fd.write('(default "" "" )')

        for key, value in sorted(i2im.imapping.items()):
            out_fd.write('(node %d "%s")\n' % (key, value))
        out_fd.write(")\n")

    @staticmethod
    def write_footer(out_fd):
        """Write the tuplip file footer"""
        out_fd.write(")\n")

    def cmad_topic_continuum_pre(self, _):
        '''Write out the one and only dependency to all the requirements.'''
        tracer.debug("Called.")
        CreateMakeDependencies.write_reqs_dep(self._cmad_file,
                                              self._output_filename)
