#include "mapstorage.h"

MapStorage::MapStorage() : modified(false), file_name("")
{
  nodemap_storage["coordinates_x"] = new Graph::NodeMap<double>(graph);
  coords.setXMap(*nodemap_storage["coordinates_x"]);
  nodemap_storage["coordinates_y"] = new Graph::NodeMap<double>(graph);
  coords.setYMap(*nodemap_storage["coordinates_y"]);

  nodemap_storage["id"] = new Graph::NodeMap<double>(graph);
  edgemap_storage["id"] = new Graph::EdgeMap<double>(graph);
}

MapStorage::~MapStorage()
{
  for (std::map<std::string, Graph::NodeMap<double>*>::const_iterator it =
      nodemap_storage.begin(); it != nodemap_storage.end(); ++it)
  {
    delete it->second;
  }
  for (std::map<std::string, Graph::EdgeMap<double>*>::const_iterator it =
      edgemap_storage.begin(); it != edgemap_storage.end(); ++it)
  {
    delete it->second;
  }
}

int MapStorage::addNodeMap(const std::string & name, Graph::NodeMap<double> *nodemap)
{
  if( nodemap_storage.find(name) == nodemap_storage.end() )
    {
      nodemap_storage[name]=nodemap;
      return 0;
    }
  return 1;
}

int MapStorage::addEdgeMap(const std::string & name, Graph::EdgeMap<double> *edgemap)
{
  if( edgemap_storage.find(name) == edgemap_storage.end() )
    {
      edgemap_storage[name]=edgemap;
      return 0;
    }
  return 1;
}

double MapStorage::maxOfNodeMap(const std::string & name)
{
  double max=0;
  for (NodeIt j(graph); j!=INVALID; ++j)
  {
    if( (*nodemap_storage[name])[j]>max )
    {
      max=(*nodemap_storage[name])[j];
    }
  }
  return max;
}

double MapStorage::maxOfEdgeMap(const std::string & name)
{
  double max=0;
  for (EdgeIt j(graph); j!=INVALID; ++j)
  {
    if( (*edgemap_storage[name])[j]>max )
    {
      max=(*edgemap_storage[name])[j];
    }
  }
  return max;
}

double MapStorage::minOfNodeMap(const std::string & name)
{
  NodeIt j(graph);
  double min=(*nodemap_storage[name])[j];
  for (; j!=INVALID; ++j)
  {
    if( (*nodemap_storage[name])[j]<min )
    {
      min=(*nodemap_storage[name])[j];
    }
  }
  return min;
}

double MapStorage::minOfEdgeMap(const std::string & name)
{
  EdgeIt j(graph);
  double min=(*edgemap_storage[name])[j];
  for (EdgeIt j(graph); j!=INVALID; ++j)
  {
    if( (*edgemap_storage[name])[j]<min )
    {
      min=(*edgemap_storage[name])[j];
    }
  }
  return min;
}

void MapStorage::initMapsForEdge(Graph::Edge e)
{
  std::map< std::string,Graph::EdgeMap<double> * >::iterator ems_it;
  for(ems_it=edgemap_storage.begin();ems_it!=edgemap_storage.end();ems_it++)
    {
      (*((*ems_it).second))[e]=5;
    }
}

void MapStorage::readFromFile(const std::string &filename)
{
  bool read_x = false;
  bool read_y = false;

  try {
    LemonReader lreader(filename);
    ContentReader content(lreader);
    lreader.run();

    const std::vector<std::string>& nodeMapNames = content.nodeSetMaps(0);
    const std::vector<std::string>& edgeMapNames = content.edgeSetMaps(0);

    GraphReader<Graph> greader(filename, graph);
    for (std::vector<std::string>::const_iterator it = nodeMapNames.begin();
        it != nodeMapNames.end(); ++it)
    {
      if (*it == "coordinates_x")
      {
        read_x = true;
        //std::cout << "read X nodemap" << std::endl;
      }
      else if (*it == "coordinates_y")
      {
        read_y = true;
        //std::cout << "read Y nodemap" << std::endl;
      }
      else if (*it == "id")
      {
        //std::cout << "read id nodemap" << std::endl;
      }
      else
      {
        nodemap_storage[*it] = new Graph::NodeMap<double>(graph);
        //std::cout << "read " << *it << " nodemap" << std::endl;
      }
      greader.readNodeMap(*it, *nodemap_storage[*it]);
    }
    for (std::vector<std::string>::const_iterator it = edgeMapNames.begin();
        it != edgeMapNames.end(); ++it)
    {
      if (*it == "id")
      {
        //std::cout << "read id edgemap" << std::endl;
      }
      else
      {
        edgemap_storage[*it] = new Graph::EdgeMap<double>(graph);
        //std::cout << "read " << *it << " edgemap" << std::endl;
      }
      greader.readEdgeMap(*it, *edgemap_storage[*it]);
    }
    greader.run();
  } catch (DataFormatError& error) {
    /*
    Gtk::MessageDialog mdialog("Read Error");
    mdialog.set_message(error.what());
    mdialog.run();
    */
    // reset graph and mapstorage ?
    return;
  }

  if (!read_x || !read_y)
  {
    int node_num = 0;
    for (NodeIt n(graph); n != INVALID; ++n)
    {
      node_num++;
    }
    const double pi = 3.142;
    double step = 2 * pi / (double) node_num;
    int i = 0;
    for (NodeIt n(graph); n != INVALID; ++n)
    {
      nodemap_storage["coordinates_x"]->set(n, 250.0 * cos(i * step));
      nodemap_storage["coordinates_y"]->set(n, 250.0 * sin(i * step));
      i++;
    }
  }
}

void MapStorage::writeToFile(const std::string &filename)
{
  GraphWriter<Graph> gwriter(filename, graph);

  for (std::map<std::string, Graph::NodeMap<double>*>::const_iterator it =
      nodemap_storage.begin(); it != nodemap_storage.end(); ++it)
  {
    gwriter.writeNodeMap(it->first, *(it->second));
    //std::cout << "wrote " << it->first << " nodemap" << std::endl;
  }
  for (std::map<std::string, Graph::EdgeMap<double>*>::const_iterator it =
      edgemap_storage.begin(); it != edgemap_storage.end(); ++it)
  {
    gwriter.writeEdgeMap(it->first, *(it->second));
    //std::cout << "wrote " << it->first << " edgemap" << std::endl;
  }
  gwriter.run();
}

void MapStorage::clear()
{
  for (std::map<std::string, Graph::NodeMap<double>*>::iterator it =
      nodemap_storage.begin(); it != nodemap_storage.end(); ++it)
  {
    if ((it->first != "coordinates_x") &&
        (it->first != "coordinates_y") &&
        (it->first != "id"))
    {
      delete it->second;
      nodemap_storage.erase(it);
    }
  }
  for (std::map<std::string, Graph::EdgeMap<double>*>::iterator it =
      edgemap_storage.begin(); it != edgemap_storage.end(); ++it)
  {
    if (it->first != "id")
    {
      delete it->second;
      edgemap_storage.erase(it);
    }
  }
  graph.clear();
  file_name = "";
  modified = false;
}
