# -*- coding: utf-8 -*-
# Copyright (c) 2008-2013 LOGILAB S.A. (Paris, FRANCE).
# http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""Utilities for creating VCG and Dot diagrams"""

from logilab.common.vcgutils import VCGPrinter
from logilab.common.graph import DotBackend

from pylint.pyreverse.utils import is_exception

class DiagramWriter(object):
    """base class for writing project diagrams
    """
    def __init__(self, config, styles):
        self.config = config
        self.pkg_edges, self.inh_edges, self.imp_edges, self.ass_edges = styles
        self.printer = None # defined in set_printer

    def write(self, diadefs):
        """write files for <project> according to <diadefs>
        """
        for diagram in diadefs:
            basename = diagram.title.strip().replace(' ', '_')
            file_name = '%s.%s' % (basename, self.config.output_format)
            self.set_printer(file_name, basename)
            if diagram.TYPE == 'class':
                self.write_classes(diagram)
            else:
                self.write_packages(diagram)
            self.close_graph()

    def write_packages(self, diagram):
        """write a package diagram"""
        # sorted to get predictable (hence testable) results
        for i, obj in enumerate(sorted(diagram.modules(), key=lambda x: x.title)):
            self.printer.emit_node(i, label=self.get_title(obj), shape='box')
            obj.fig_id = i
        # package dependencies
        for rel in diagram.get_relationships('depends'):
            self.printer.emit_edge(rel.from_object.fig_id, rel.to_object.fig_id,
                                   **self.pkg_edges)

    def write_classes(self, diagram):
        """write a class diagram"""
        # sorted to get predictable (hence testable) results
        for i, obj in enumerate(sorted(diagram.objects, key=lambda x: x.title)):
            self.printer.emit_node(i, **self.get_values(obj))
            obj.fig_id = i
        # inheritance links
        for rel in diagram.get_relationships('specialization'):
            self.printer.emit_edge(rel.from_object.fig_id, rel.to_object.fig_id,
                                   **self.inh_edges)
        # implementation links
        for rel in diagram.get_relationships('implements'):
            self.printer.emit_edge(rel.from_object.fig_id, rel.to_object.fig_id,
                                   **self.imp_edges)
        # generate associations
        for rel in diagram.get_relationships('association'):
            self.printer.emit_edge(rel.from_object.fig_id, rel.to_object.fig_id,
                                   label=rel.name, **self.ass_edges)

    def set_printer(self, file_name, basename):
        """set printer"""
        raise NotImplementedError

    def get_title(self, obj):
        """get project title"""
        raise NotImplementedError

    def get_values(self, obj):
        """get label and shape for classes."""
        raise NotImplementedError

    def close_graph(self):
        """finalize the graph"""
        raise NotImplementedError


class DotWriter(DiagramWriter):
    """write dot graphs from a diagram definition and a project
    """

    def __init__(self, config):
        styles = [dict(arrowtail='none', arrowhead="open"),
                  dict(arrowtail='none', arrowhead='empty'),
                  dict(arrowtail='node', arrowhead='empty', style='dashed'),
                  dict(fontcolor='green', arrowtail='none',
                       arrowhead='diamond', style='solid'),
                 ]
        DiagramWriter.__init__(self, config, styles)

    def set_printer(self, file_name, basename):
        """initialize DotWriter and add options for layout.
        """
        layout = dict(rankdir="BT")
        self.printer = DotBackend(basename, additionnal_param=layout)
        self.file_name = file_name

    def get_title(self, obj):
        """get project title"""
        return obj.title

    def get_values(self, obj):
        """get label and shape for classes.

        The label contains all attributes and methods
        """
        label = obj.title
        if obj.shape == 'interface':
            label = u'«interface»\\n%s' % label
        if not self.config.only_classnames:
            label = r'%s|%s\l|' % (label, r'\l'.join(obj.attrs))
            for func in obj.methods:
                label = r'%s%s()\l' % (label, func.name)
            label = '{%s}' % label
        if is_exception(obj.node):
            return dict(fontcolor='red', label=label, shape='record')
        return dict(label=label, shape='record')

    def close_graph(self):
        """print the dot graph into <file_name>"""
        self.printer.generate(self.file_name)


class VCGWriter(DiagramWriter):
    """write vcg graphs from a diagram definition and a project
    """
    def __init__(self, config):
        styles = [dict(arrowstyle='solid', backarrowstyle='none',
                       backarrowsize=0),
                  dict(arrowstyle='solid', backarrowstyle='none',
                       backarrowsize=10),
                  dict(arrowstyle='solid', backarrowstyle='none',
                       linestyle='dotted', backarrowsize=10),
                  dict(arrowstyle='solid', backarrowstyle='none',
                       textcolor='green'),
                 ]
        DiagramWriter.__init__(self, config, styles)

    def set_printer(self, file_name, basename):
        """initialize VCGWriter for a UML graph"""
        self.graph_file = open(file_name, 'w+')
        self.printer = VCGPrinter(self.graph_file)
        self.printer.open_graph(title=basename, layoutalgorithm='dfs',
                                late_edge_labels='yes', port_sharing='no',
                                manhattan_edges='yes')
        self.printer.emit_node = self.printer.node
        self.printer.emit_edge = self.printer.edge

    def get_title(self, obj):
        """get project title in vcg format"""
        return r'\fb%s\fn' % obj.title

    def get_values(self, obj):
        """get label and shape for classes.

        The label contains all attributes and methods
        """
        if is_exception(obj.node):
            label = r'\fb\f09%s\fn' % obj.title
        else:
            label = r'\fb%s\fn' % obj.title
        if obj.shape == 'interface':
            shape = 'ellipse'
        else:
            shape = 'box'
        if not self.config.only_classnames:
            attrs = obj.attrs
            methods = [func.name for func in obj.methods]
            # box width for UML like diagram
            maxlen = max(len(name) for name in [obj.title] + methods + attrs)
            line = '_' * (maxlen + 2)
            label = r'%s\n\f%s' % (label, line)
            for attr in attrs:
                label = r'%s\n\f08%s' % (label, attr)
            if attrs:
                label = r'%s\n\f%s' % (label, line)
            for func in methods:
                label = r'%s\n\f10%s()' % (label, func)
        return dict(label=label, shape=shape)

    def close_graph(self):
        """close graph and file"""
        self.printer.close_graph()
        self.graph_file.close()

