// src/xml_serializer_factory.cc - Copyright 2005, 2006, University
//               of Padova, dept. of Pure and Applied
//               Mathematics
//
// This file is part of SGPEMv2.
//
// This 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.
//
// SGPEMv2 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 SGPEMv2; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

#include "xml_serializer_factory.hh"

#include <sgpemv2/string_utils.hh>
#include <sgpemv2/history.hh>
#include <sgpemv2/resource.hh>

using namespace sgpem;



#include <iostream>
using namespace std;


XMLSerializerFactory::XMLSerializerFactory(History& hist)
    : _hist(&hist)
{}

XMLSerializerFactory::~XMLSerializerFactory()
{}

History* XMLSerializerFactory::get_history()
{
  return _hist;
}

void
XMLSerializerFactory::factory_method(const Glib::ustring& class_name, Parameters& parameters) throw(SerializerError)
{
  if (class_name == "Resource")
  {
    create_resource(parameters);
  }
  else if (class_name == "Process")
  {
    create_process(parameters);
  }
  else if (class_name == "Thread")
  {
    create_thread(parameters);
  }
  else if (class_name == "Request")
  {
    create_request(parameters);
  }
  else if (class_name == "SubRequest")
  {
    create_subrequest(parameters);
  }
  else
  {
    throw SerializerError("Factory for Unknown class: " + class_name + " doesn't exists.");
  }
}

History::ResourcePair
XMLSerializerFactory::create_resource(Parameters& parameters)
{
  // if(_hist!=NULL)
  {

    Glib::ustring name;
    Glib::ustring key("0");
    int arrival_time = 0;
    int how_many = 1;
    bool preemptable = false;
    int old_key;
    Parameters::iterator pos;

    // read "name" property
    pos = parameters.find(Glib::ustring("name"));
    if (pos != parameters.end())
    {
      name = pos->second;
    }

    // read "key" property
    pos = parameters.find(Glib::ustring("id"));
    if (pos != parameters.end())
    {
      Glib::ustring id = key = pos->second;
      if (id.length() > 6 && id.substr(0, 6) == Glib::ustring("reskey"))
      {
        key = id.substr(6);
        old_key = string_to<int>(key);
      }
    }

    // read "preemptable" property
    pos = parameters.find(Glib::ustring("preemptable"));
    if (pos != parameters.end())
    {
      preemptable = (pos->second == "true");
    }

    // read "arrival-time" property
    pos = parameters.find(Glib::ustring("arrival-time"));
    if (pos != parameters.end())
    {
      arrival_time = string_to<int>(pos->second);
    }

    // read "how-many" property
    pos = parameters.find(Glib::ustring("how-many"));
    if (pos != parameters.end())
    {
      how_many = string_to<int>(pos->second);
    }


    History::ResourcePair respair = _hist->add_resource(name, preemptable, how_many, arrival_time);
    _temp_map.insert(TempMap::value_type((resource_key_t)old_key, respair.first));

    return respair;
  }

}

Process&
XMLSerializerFactory::create_process(Parameters& parameters)
{
  // if(_hist!=NULL)
  {

    Glib::ustring name;
    int arrival_time = 0;
    int priority = 1;
    Parameters::iterator pos;

    // read "name" property
    pos = parameters.find(Glib::ustring("name"));
    if (pos != parameters.end())
    {
      name = pos->second;
    }

    // read "arrival-time" property
    pos = parameters.find(Glib::ustring("arrival-time"));
    if (pos != parameters.end())
    {
      arrival_time = string_to<int>(pos->second);
    }

    // read "priority" property
    pos = parameters.find(Glib::ustring("priority"));
    if (pos != parameters.end())
    {
      priority = string_to<int>(pos->second);
    }

    _last_process = &_hist->add_process(name, arrival_time, priority);
    return *_last_process;
  }
}



Thread&
XMLSerializerFactory::create_thread(Parameters& parameters)
{
  // if(_hist!=NULL)
  {

    Glib::ustring name;
    int arrival_time = 0;
    int lasts_for = 0;
    int priority = 1;
    Parameters::iterator pos;

    // read "name" property
    pos = parameters.find(Glib::ustring("name"));
    if (pos != parameters.end())
    {
      name = pos->second;
    }

    // read "arrival-time" property
    pos = parameters.find(Glib::ustring("arrival-delta"));
    if (pos != parameters.end())
    {
      arrival_time = string_to<int>(pos->second);
    }

    // read "priority" property
    pos = parameters.find(Glib::ustring("priority"));
    if (pos != parameters.end())
    {
      priority = string_to<int>(pos->second);
    }

    // read "priority" property
    pos = parameters.find(Glib::ustring("lasts-for"));
    if (pos != parameters.end())
    {
      lasts_for = string_to<int>(pos->second);
    }

    _last_thread = &_hist->add_thread(name, *_last_process, lasts_for, arrival_time, priority);
    return *_last_thread;
  }
}

Request&
XMLSerializerFactory::create_request(Parameters& parameters)
{
  // if(_hist!=NULL)
  {

    int arrival_time = 0;
    Parameters::iterator pos;

    // read "arrival-time" property
    pos = parameters.find(Glib::ustring("arrival-time"));
    if (pos != parameters.end())
    {
      arrival_time = string_to<int>(pos->second);
    }

    _last_request = &_hist->add_request(*_last_thread, arrival_time);
    return *_last_request;
  }
}

SubRequest&
XMLSerializerFactory::create_subrequest(Parameters& parameters)
{
  // if(_hist!=NULL)
  {

    int old_key = 0;
    int lasts_for = 0;
    Parameters::iterator pos;
    resource_key_t new_key = 0;


    // read "resource" property
    pos = parameters.find(Glib::ustring("resource"));
    if (pos != parameters.end())
    {
      old_key = string_to<int>(pos->second);

      TempMap::iterator temp_pos;
      temp_pos = _temp_map.find((resource_key_t)old_key);
      if (temp_pos != _temp_map.end())
      {
        //take key of resource in _hist
        new_key = temp_pos->second;
      }
    }

    // read "lasts-for" property
    pos = parameters.find(Glib::ustring("lasts-for"));
    if (pos != parameters.end())
    {
      lasts_for = string_to<int>(pos->second);
    }

    return _hist->add_subrequest(*_last_request, new_key, (History::time_t)lasts_for);
  }
  // add a sub request - Request, resource_key, duration
}




/* comment */
