
//  This file forms part of the GOBLIN C++ Class Library.
//
//  Initially written by Christian Fremuth-Paeger, March 2007
//
//  Copying, compiling, distribution and modification
//  of this source code is permitted only in accordance
//  with the GOBLIN general licence information.

/// \file   exportToDot.cpp
/// \brief  #exportToDot class implementation

#include "exportToDot.h"


exportToDot::exportToDot(const abstractMixedGraph& GG,const char* expFileName)
    throw(ERFile) : canvasBuilder(GG), expFile(expFileName, ios::out)
{
    if (!expFile)
    {
        sprintf(CT.logBuffer,"Could not open export file %s, io_state %d",
            expFileName,expFile.rdstate());
        Error(ERR_FILE,"exportToDot",CT.logBuffer);
    }

    expFile.flags(expFile.flags() | ios::right);
    expFile.setf(ios::floatfield);
    expFile.precision(5);

    if (G.IsUndirected())
    {
        expFile << "graph G {" << endl;
    }
    else
    {
        expFile << "digraph G {" << endl;
    }
}


unsigned long exportToDot::Size() const throw()
{
    return
          sizeof(exportToDot)
        + managedObject::Allocated();
}


unsigned long exportToDot::Allocated() const throw()
{
    return 0;
}


void exportToDot::WriteArc(TArc a,TNode u,TNode v,TLineStyle lineStyle,int width,
    TArrowDir displayedArrows,TIndex colourIndex,int depth) throw()
{
    char* rgbColour = NULL;

    if (colourIndex==OUTLINE_COLOUR)
    {
        rgbColour = "#000000";
    }
    else if (colourIndex==GRID_COLOUR)
    {
        rgbColour = "#A0A0A0";
    }
    else if (colourIndex==PRED_COLOUR)
    {
        rgbColour = predColour;
    }
    else if (arcColourMode==ARCS_FLOATING_COLOURS)
    {
        rgbColour = SmoothColour(colourIndex - ZERO_COLOUR,
                                 maxEdgeColour,MAX_COLOUR);
    }
    else
    {
        rgbColour = FixedEdgeColour(colourIndex - ZERO_COLOUR);
    }

    expFile << "  v" << u;

    if (displayedArrows==ARROW_FORWARD)
    {
        expFile << " -> ";
    }
    else
    {
        expFile << " -- ";
    }

    expFile << "v" << v << " ";

    expFile << "[color = \"" << rgbColour << "\", label = \"";

    ComposeArcLabel(a,expFile);

    expFile << "\"";

    if (lineStyle==LINE_STYLE_DOT)
    {
        expFile << ", style = dotted";
    }
    else if (lineStyle==LINE_STYLE_DASH)
    {
        expFile << ", style = dashed";
    }
    else if (lineStyle==LINE_STYLE_DASH_DOT)
    {
        expFile << ", style = bold";
    }

    expFile << "];" << endl;
}


void exportToDot::DisplayNode(TNode v) throw()
{
    expFile << "  v" << v << " [";

    char* fillColour = "#ffffff";

    if (nodeColourMode==NODES_COLOUR_BY_DISTANCE)
    {
        if (G.Dist(v)==InfFloat || G.Dist(v)==-InfFloat) fillColour = inftyColour;
    }
    else if (nodeColourMode==NODES_FIXED_COLOURS)
    {
        fillColour = FixedNodeColour(G.NodeColour(v));
    }
    else if (nodeColourMode==NODES_COLOUR_BY_DEMAND)
    {
        if (G.Demand(v)>0) fillColour = FixedNodeColour(1);
        if (G.Demand(v)<0) fillColour = FixedNodeColour(2);
    }
    else if (nodeColourMode==NODES_FLOATING_COLOURS)
    {
        fillColour = SmoothColour(G.NodeColour(v),maxNodeColour,NO_COLOUR);
    }

    expFile << "style = filled, fillcolor = \"" << fillColour << "\", label = \"";

    ComposeNodeLabel(v,expFile);

    expFile << "\", shape = ";

    switch (nodeShapeMode)
    {
        case NODE_SHAPE_POINT:
        {
            expFile << "point";
            break;
        }
        case NODE_SHAPE_CIRCULAR:
        {
            expFile << "circle";
            break;
        }
        case NODE_SHAPE_BOX:
        {
            expFile << "box";
            break;
        }
        case NODE_SHAPE_BY_COLOUR:
        {
            if (G.NodeColour(v)==0)
            {
                expFile << "circle";
            }
            else
            {
                expFile << "box";
            }

            break;
        }
    }

    expFile << "];" << endl;
}


exportToDot::~exportToDot() throw()
{
    expFile << "}" << endl;
    expFile.close();
}
