// ==========================================================================
//                 SeqAn - The Library for Sequence Analysis
// ==========================================================================
// Copyright (c) 2006-2013, Knut Reinert, FU Berlin
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
//       its contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// ==========================================================================

#ifndef SEQAN_HEADER_TEST_GRAPH_UTILS_H
#define SEQAN_HEADER_TEST_GRAPH_UTILS_H

using namespace seqan;

//////////////////////////////////////////////////////////////////////////////

template <typename TGraph>
void  Test_GraphDrawing_Tmp(char const * EXPECTED)
{
    // Create a dummy graph
    TGraph g;
    addVertex(g);addVertex(g);addEdge(g,0,1);
    addVertex(g);addEdge(g,0,2);addVertex(g); 
    addVertex(g);addVertex(g);addEdge(g,3,4);

    // Dot Drawing
    std::stringstream sstream;
    sstream << g;
    SEQAN_ASSERT_EQ(EXPECTED, sstream.str());
}

//////////////////////////////////////////////////////////////////////////////

void  Test_GraphDrawing()
{
    typedef Position<String<char> >::Type TPosition;

    char const * EXPECTED_DIRECTED =
            "Adjacency list:\n"
            "0 -> 2,1,\n"
            "1 -> \n"
            "2 -> \n"
            "3 -> 4,\n"
            "4 -> \n"
            "5 -> \n"
            "Edge list:\n"
            "Source: 0,Target: 2 (Id: 1)\n"
            "Source: 0,Target: 1 (Id: 0)\n"
            "Source: 3,Target: 4 (Id: 2)\n";
    char const * EXPECTED_UNDIRECTED =
            "Adjacency list:\n"
            "0 -> 2,1,\n"
            "1 -> 0,\n"
            "2 -> 0,\n"
            "3 -> 4,\n"
            "4 -> 3,\n"
            "5 -> \n"
            "Edge list:\n"
            "Source: 0,Target: 2 (Id: 1)\n"
            "Source: 0,Target: 1 (Id: 0)\n"
            "Source: 3,Target: 4 (Id: 2)\n";
    char const * EXPECTED_TREE =
            "Adjacency list:\n"
            "0 -> 2,1,\n"
            "1 -> \n"
            "2 -> \n"
            "3 -> 4,\n"
            "4 -> \n"
            "5 -> \n"
            "Edge list:\n"
            "Source: 0,Target: 2 (Id: 2)\n"
            "Source: 0,Target: 1 (Id: 1)\n"
            "Source: 3,Target: 4 (Id: 4)\n";
    Test_GraphDrawing_Tmp<Graph<Directed<> > >(EXPECTED_DIRECTED);
    Test_GraphDrawing_Tmp<Graph<Undirected<> > >(EXPECTED_UNDIRECTED);
    Test_GraphDrawing_Tmp<Graph<Tree<> > >(EXPECTED_TREE);

    // Automat
    Graph<Automaton<Dna> > automat;
    createRoot(automat);addVertex(automat);addEdge(automat,0,1,'a');
    addVertex(automat);addEdge(automat,0,2,'g');
    // Dot Drawing

    {
        std::stringstream sstream;
        write(sstream, automat, DotDrawing());
        char const * EXPECTED =
                "digraph G {\n"
                "\n"
                "/* Graph Attributes */\n"
                "graph [rankdir = LR];\n"
                "\n"
                "/* Node Attributes */\n"
                "node [shape = rectangle, fillcolor = white, style = filled, fontname = \"Times-Italic\"];\n"
                "\n"
                "/* Edge Attributes */\n"
                "edge [fontname = \"Times-Italic\", arrowsize = 0.75, fontsize = 16];\n"
                "\n"
                "/* Nodes */\n"
                "0 [label = \"0\", shape = doublecircle];\n"
                "1 [label = \"1\"];\n"
                "2 [label = \"2\"];\n"
                "\n"
                "/* Edges */\n"
                "0 -> 1 [label = \"A\"];\n"
                "0 -> 2 [label = \"G\"];\n"
                "\n"
                "}\n";
        SEQAN_ASSERT_EQ(EXPECTED, sstream.str());
    }

    // Trie
    Graph<Automaton<char> > trie;
    String<String<TPosition> > pos;
    String<String<char> > keywords;
    appendValue(keywords, String<char>("announce"));
    appendValue(keywords, String<char>("annual"));
    appendValue(keywords, String<char>("annually"));
    createTrie(trie,pos,keywords);
    // Dot Drawing
    String<String<char> > nodeMap;
    _createTrieNodeAttributes(trie, pos, nodeMap);
    String<String<char> > edgeMap;
    _createEdgeAttributes(trie,edgeMap);
    {
        std::stringstream sstream;
        char const * EXPECTED =
                "digraph G {\n"
                "\n"
                "/* Graph Attributes */\n"
                "graph [rankdir = LR];\n"
                "\n"
                "/* Node Attributes */\n"
                "node [shape = rectangle, fillcolor = white, style = filled, fontname = \"Times-Italic\"];\n"
                "\n"
                "/* Edge Attributes */\n"
                "edge [fontname = \"Times-Italic\", arrowsize = 0.75, fontsize = 16];\n"
                "\n"
                "/* Nodes */\n"
                "0 [label = \"0\", shape = doublecircle];\n"
                "1 [label = \"1\"];\n"
                "2 [label = \"2\"];\n"
                "3 [label = \"3\"];\n"
                "4 [label = \"4\"];\n"
                "5 [label = \"5\"];\n"
                "6 [label = \"6\"];\n"
                "7 [label = \"7\"];\n"
                "8 [shape = box, label = \"8 {0}\"];\n"
                "9 [label = \"9\"];\n"
                "10 [label = \"10\"];\n"
                "11 [shape = box, label = \"11 {1}\"];\n"
                "12 [label = \"12\"];\n"
                "13 [shape = box, label = \"13 {2}\"];\n"
                "\n"
                "/* Edges */\n"
                "0 -> 1 [label = \"a\"];\n"
                "1 -> 2 [label = \"n\"];\n"
                "2 -> 3 [label = \"n\"];\n"
                "3 -> 4 [label = \"o\"];\n"
                "3 -> 9 [label = \"u\"];\n"
                "4 -> 5 [label = \"u\"];\n"
                "5 -> 6 [label = \"n\"];\n"
                "6 -> 7 [label = \"c\"];\n"
                "7 -> 8 [label = \"e\"];\n"
                "9 -> 10 [label = \"a\"];\n"
                "10 -> 11 [label = \"l\"];\n"
                "11 -> 12 [label = \"l\"];\n"
                "12 -> 13 [label = \"y\"];\n"
                "\n"
                "}\n";
        write(sstream, trie, nodeMap, edgeMap, DotDrawing());
        SEQAN_ASSERT_EQ(EXPECTED, sstream.str());
    }

    // WordGraph
    typedef Graph<Automaton<Dna, String<Dna>, WordGraph<> > > TWordGraph;
    TWordGraph wordGr;
    addVertex(wordGr);addVertex(wordGr);addVertex(wordGr);addVertex(wordGr);
    assignRoot(wordGr,3);root(wordGr) = 2;addEdge(wordGr,0,3,"ag");
    addVertex(wordGr);addVertex(wordGr);addEdge(wordGr,0,5,"g");
    addVertex(wordGr);addVertex(wordGr);addEdge(wordGr,3,1,"aggg");
    addEdge(wordGr,3,4,"gg");addEdge(wordGr,5,2,"aggg");addEdge(wordGr,5,7,"g");
    addEdge(wordGr,7,6,"g");assignRoot(wordGr,0);
    {
        std::stringstream sstream;
        char const * EXPECTED =
                "digraph G {\n"
                "\n"
                "/* Graph Attributes */\n"
                "graph [rankdir = LR];\n"
                "\n"
                "/* Node Attributes */\n"
                "node [shape = rectangle, fillcolor = white, style = filled, fontname = \"Times-Italic\"];\n"
                "\n"
                "/* Edge Attributes */\n"
                "edge [fontname = \"Times-Italic\", arrowsize = 0.75, fontsize = 16];\n"
                "\n"
                "/* Nodes */\n"
                "0 [label = \"0\", shape = doublecircle];\n"
                "1 [label = \"1\"];\n"
                "2 [label = \"2\"];\n"
                "3 [label = \"3\"];\n"
                "4 [label = \"4\"];\n"
                "5 [label = \"5\"];\n"
                "6 [label = \"6\"];\n"
                "7 [label = \"7\"];\n"
                "\n"
                "/* Edges */\n"
                "0 -> 3 [label = \"AG\"];\n"
                "0 -> 5 [label = \"G\"];\n"
                "3 -> 1 [label = \"AGGG\"];\n"
                "3 -> 4 [label = \"GG\"];\n"
                "5 -> 2 [label = \"AGGG\"];\n"
                "5 -> 7 [label = \"G\"];\n"
                "7 -> 6 [label = \"G\"];\n"
                "\n"
                "}\n";
        write(sstream, wordGr,DotDrawing());
        SEQAN_ASSERT_EQ(EXPECTED, sstream.str());
    }
}

    
//////////////////////////////////////////////////////////////////////////////


void Test_GraphUtils()
{
    Test_GraphDrawing();
}

//////////////////////////////////////////////////////////////////////////////

SEQAN_DEFINE_TEST(test_graph_utils)
{
    Test_GraphUtils();
}

#endif

