#
# pGRAPH
# Copyright (C) 2006 Pedram Amini <pedram.amini@gmail.com>
#
# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#

import pydot


class Edge:
    id = None
    src = None
    dst = None

    # general graph attributes.
    color = 0x000000
    label = ""

    # gml relevant attributes.
    gml_arrow = "none"
    gml_stipple = 1
    gml_line_width = 1.0

    def __init__(self, src, dst):
        """
        Class constructor.

        @type  src: Mixed
        @param src: Edge source
        @type  dst: Mixed
        @param dst: Edge destination
        """

        # the unique id for any edge (provided that duplicates are not allowed) is the combination of the source and
        # the destination stored as a long long.
        self.id = (src << 32) + dst
        self.src = src
        self.dst = dst

        # general graph attributes.
        self.color = 0x000000
        self.label = ""

        # gml relevant attributes.
        self.gml_arrow = "none"
        self.gml_stipple = 1
        self.gml_line_width = 1.0

    def render_edge_gml(self, graph):
        """
        Render an edge description suitable for use in a GML file using the set internal attributes.

        @type  graph: pgraph.Graph
        @param graph: Top level graph object containing the current edge

        @rtype:  String
        @return: GML edge description
        """

        src = graph.find_node("id", self.src)
        dst = graph.find_node("id", self.dst)

        # ensure nodes exist at the source and destination of this edge.
        if not src or not dst:
            return ""

        edge = (
            "  edge [\n"
            "    source {srcNumber}\n"
            "    target {dstNumber}\n"
            "    generalization 0\n"
            "    graphics [\n"
            '      type "line"\n'
            '      arrow "{gml_arrow}"\n'
            "      stripple {gml_stipple}\n"
            "      linWidth {gml_line_width}\n"
            '      fill "#{color:06x}"\n'
            "    ]\n"
            "  ]\n".format(
                color=self.color,
                srcNumber=src.number,
                dstNumber=dst.number,
                gml_arrow=self.gml_arrow,
                gml_stipple=self.gml_stipple,
                gml_line_width=self.gml_line_width,
            )
        )

        return edge

    def render_edge_graphviz(self):
        """
        Render an edge suitable for use in a Pydot graph using the set internal attributes.

        @rtype:  pydot.Edge()
        @return: Pydot object representing edge
        """

        # no need to validate if nodes exist for src/dst. graphviz takes care of that for us transparently.

        dot_edge = pydot.Edge(self.src, self.dst)

        if self.label:
            dot_edge.label = self.label

        dot_edge.color = "#{:06x}".format(self.color)

        return dot_edge

    def render_edge_udraw(self, graph):
        """
        Render an edge description suitable for use in a GML file using the set internal attributes.

        @type  graph: pgraph.Graph
        @param graph: Top level graph object containing the current edge

        @rtype:  String
        @return: GML edge description
        """

        src = graph.find_node("id", self.src)
        dst = graph.find_node("id", self.dst)

        # ensure nodes exist at the source and destination of this edge.
        if not src or not dst:
            return ""

        # translate newlines for uDraw.
        self.label = self.label.replace("\n", "\\n")

        udraw = (
            '        l("{src:08x}->{dst:08x}",\n'
            '          e("",\n'
            "            [\n"
            '              a("EDGECOLOR","#{color:06x}"),\n'
            '              a("OBJECT","{label}")\n'
            "            ],\n"
            '          r("{dst:08x}")\n'
            "        )\n".format(src=self.src, dst=self.dst, color=self.color, label=self.label)
        )

        return udraw

    def render_edge_udraw_update(self):
        """
        Render an edge update description suitable for use in a GML file using the set internal attributes.

        @rtype:  String
        @return: GML edge update description
        """

        # translate newlines for uDraw.
        self.label = self.label.replace("\n", "\\n")

        udraw = (
            '\n  new_edge("{src:08x}->{dst:08x}","",\n'
            "    [\n"
            '      a("EDGECOLOR","#{color:06x}"),\n'
            '      a("OBJECT","{label}")\n'
            "    ]\n"
            '    "{src:08x}", "{dst:08x}"\n'
            "  )\n".format(src=self.src, dst=self.dst, color=self.color, label=self.label)
        )

        return udraw
