#include <tulip/Graph.h>
#include <tulip/TlpTools.h>
#include <tulip/PluginLoaderTxt.h>
#include <tulip/PluginLibraryLoader.h>
#include <tulip/ColorProperty.h>
#include <tulip/StringProperty.h>
#include <tulip/DoubleProperty.h>

using namespace std;
using namespace tlp;

int main(int, char **) {

  /*
   * Let's create the following graph
   *
   *      A
   *    /   \
   *  B       C
   *   \     /
   *    D - E
   */

  /*
   Initialize the library and load all plugins
   */
  tlp::initTulipLib();
  PluginLoaderTxt loadertxt;
  PluginLibraryLoader::loadPlugins(&loadertxt);

  // create a new graph
  Graph *myGraph = tlp::newGraph();

  node a = myGraph->addNode();
  node b = myGraph->addNode();
  node c = myGraph->addNode();
  node d = myGraph->addNode();
  node e = myGraph->addNode();

  myGraph->addEdge(a, b);
  myGraph->addEdge(a, c);
  myGraph->addEdge(b, d);
  myGraph->addEdge(c, e);
  myGraph->addEdge(d, e);

  // now in color. 'viewColor' is the Tulip GUI's default color property, so when we load it we will
  // see the color immediately
  // If 'viewColor' did not exist before, this creates it.
  ColorProperty *color = myGraph->getProperty<ColorProperty>("viewColor");
  color->setNodeValue(a, Color(255, 0, 0));
  color->setNodeValue(b, Color(0, 255, 0));
  color->setNodeValue(c, Color(0, 0, 255));
  color->setNodeValue(d, Color(255, 0, 0));
  color->setNodeValue(e, Color(0, 255, 0));
  // hey look, this is a 3-coloration :)

  // set the label of the nodes (again, with Tulip's default label property)
  StringProperty *label = myGraph->getProperty<StringProperty>("viewLabel");
  label->setNodeValue(a, "A");
  label->setNodeValue(b, "B");
  label->setNodeValue(c, "C");
  label->setNodeValue(d, "D");
  label->setNodeValue(e, "E");

  DoubleProperty *metric = myGraph->getProperty<DoubleProperty>("degree");

  // if the degree plugin is available, let's call it.
  if (tlp::PluginLister::pluginExists("Degree")) {
    // now compute the degree of the nodes.
    string errorMessage;
    // this calls the Tulip plugin 'Degree'.
    bool success = myGraph->applyPropertyAlgorithm("Degree", metric, errorMessage);

    if (!success) {
      std::cout << errorMessage << std::endl;
    }
  } else {
    std::cout << "could not find the plugin, computing" << std::endl;
    for (auto n : myGraph->nodes()) {
      metric->setNodeValue(n, myGraph->deg(n));
    }
  }

  // output the degree of node a;
  std::cout << metric->getNodeValue(a) << std::endl;

  // saveGraph is a shortcut ofr exportGraph that uses the TLP export.
  tlp::saveGraph(myGraph, "mygraph.tlp");

  return EXIT_SUCCESS;
}
