// src/global_preferences.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 "config.h"

#include <sgpemv2/global_preferences.hh>
#include <sgpemv2/key_file.hh>
#include <sgpemv2/string_utils.hh>

#include <sstream>

// Do not include in header file:
#include <sgpemv2/templates/singleton.tcc>

using namespace sgpem;

// Explicit template instantiation to allow to export symbols from the DSO.
template class SG_DLLEXPORT Singleton<GlobalPreferences>;

GlobalPreferences::GlobalPreferences()
    : _mod_dirs(1, PLUGDIR), _pol_dirs(1, POLDIR), _speed(1000)
{}


GlobalPreferences::dir_iterator
GlobalPreferences::policies_dir_begin() const
{
  return _pol_dirs.begin();
}


GlobalPreferences::dir_iterator
GlobalPreferences::policies_dir_end() const
{
  return _pol_dirs.end();
}


GlobalPreferences::dir_iterator
GlobalPreferences::modules_dir_begin() const
{
  return _mod_dirs.begin();
}


GlobalPreferences::dir_iterator
GlobalPreferences::modules_dir_end() const
{
  return _mod_dirs.end();
}


const
Glib::ustring
GlobalPreferences::get_config_filename()
{
  return Glib::ustring("sgpem.cfg");
}

void
GlobalPreferences::add_modules_dir(const Glib::ustring& moddir)
{
  _mod_dirs.insert(_mod_dirs.begin(), moddir);
}


void
GlobalPreferences::add_policies_dir(const Glib::ustring& poldir)
{
  _pol_dirs.insert(_pol_dirs.begin(), poldir);
}

std::vector<Glib::ustring>&
GlobalPreferences::get_policy_dirs()
{
  return _pol_dirs;
}

std::vector<Glib::ustring>&
GlobalPreferences::get_plugin_dirs()
{
  return _mod_dirs;
}

int
GlobalPreferences::get_speed()
{
  return _speed;
}

int
GlobalPreferences::set_speed(int new_speed)
{
  int old_speed = _speed;
  _speed = new_speed;
  return old_speed;
}

Glib::ustring 
GlobalPreferences::get_schedulable_color(Schedulable::state st) const
{
  switch(st)
  {
  case Schedulable::state_running:
    return "ForestGreen";
  case Schedulable::state_ready:
    return "GoldenRod";
  case Schedulable::state_blocked:
    return "red";
  case Schedulable::state_terminated:
    return "DarkSlateGray";
  case Schedulable::state_future:
    return "Gray";
  default:
    return "black";
  }
}

Glib::ustring 
GlobalPreferences::get_request_color(Request::state st) const
{
  switch(st)
  {
  case Request::state_allocated:
    return "ForestGreen";
  case Request::state_allocable:
    return "GoldenRod";
  case Request::state_unallocable:
    return "red";
  case Request::state_exhausted:
    return "DarkSlateGray";
  case Request::state_future:
    return "Gray";
  default:
    return "black";
  }
}
    
void
GlobalPreferences::write_configrc()
{
  KeyFile kf;

  key_file_write(kf);
  kf.file_write(get_config_filename());
}

void
GlobalPreferences::load_configrc()
{
  KeyFile kf;

  kf.file_read(get_config_filename());
  key_file_read(kf);
}

void
GlobalPreferences::write_configrc(std::ostream &os)
{
  KeyFile kf;

  key_file_write(kf);
  kf.file_write(os);
}

void
GlobalPreferences::load_configrc(std::istream &is)
{
  KeyFile kf;

  kf.file_read(is);
  key_file_read(kf);
}


void
GlobalPreferences::key_file_read(KeyFile& kf)
{

  _mod_dirs.clear();
  _pol_dirs.clear();
  std::vector<Glib::ustring>  old_mod_dirs(1, PLUGDIR);
  std::vector<Glib::ustring>  old_pol_dirs(1, POLDIR);
  _mod_dirs = old_mod_dirs;
  _pol_dirs = old_pol_dirs;


  // read speed
  {
    int new_speed = 1000; // use a default value
    const Glib::ustring* val = kf.search_value(Glib::ustring("speed"));
    if (val)
    {
      new_speed = string_to<int>(*val);
      set_speed(new_speed);
    }
  }
  // read modules directories
  {
    const Glib::ustring* val = kf.search_value(Glib::ustring("modules-dir-number"));
    if (val)
    {
      std::istringstream istr(val->c_str());
      int n;
      istr >> n;
      for (int i = 1; i <= n; i++)
      {
        std::ostringstream ostr;
        ostr << "modules-dir-" << i;
        Glib::ustring key(ostr.str());
        val = kf.search_value(key);
        if (val && *val != _mod_dirs[0])
        {
          // add_modules_dir(*val);
          _mod_dirs.push_back(*val);
        }
      }
    }
 }

  // read policies directories
  {
    const Glib::ustring* val = kf.search_value(Glib::ustring("policies-dir-number"));
    if (val)
    {
      std::istringstream istr(val->c_str());
      int n;
      istr >> n;
      for (int i = 1; i <= n; i++)
      {
        std::ostringstream ostr;
        ostr << "policies-dir-" << i;
        Glib::ustring key(ostr.str().c_str());
        val = kf.search_value(key);
        if (val && *val != _pol_dirs[0])
        {
          // add_policies_dir(*val);
          _pol_dirs.push_back(*val);
        }
      }
    }
  }


}

void
GlobalPreferences::key_file_write(KeyFile& kf)
{
  // write speed
  {
    Glib::ustring key("speed");
    Glib::ustring value;
    to_string<int>(_speed, value);
    kf.insert_key_value(key, value);
  }

  // add modules directories
  {
    /*
    GlobalPreferences::dir_iterator iter=_globalPreferences.modules_dir_begin();
    */
    dir_iterator iter = _mod_dirs.begin();
    dir_iterator end = _mod_dirs.end();
    int n = 0;
    while (iter != end)
    {
      std::ostringstream ostr;
      n++;
      ostr << "modules-dir-" << n; // << std::ends;
      Glib::ustring key(ostr.str().c_str());
      kf.insert_key_value(key, (*iter));
      ++iter;
    }
    Glib::ustring key("modules-dir-number");
    std::ostringstream ostr;
    ostr << n << std::ends;
    Glib::ustring value(ostr.str().c_str());
    kf.insert_key_value(key, value);
  }
  // add policies directories
  {
    /*
        GlobalPreferences::dir_iterator iter=_globalPreferences.policies_dir_begin();
       */
    dir_iterator iter = _pol_dirs.begin();
    dir_iterator end = _pol_dirs.end();
    int n = 0;
    while (iter != end)
    {
      std::ostringstream ostr;
      n++;
      ostr << "policies-dir-" << n; // << std::ends;
      Glib::ustring key(ostr.str().c_str());
      kf.insert_key_value(key, (*iter));
      ++iter;
    }
    Glib::ustring key("policies-dir-number");
    std::ostringstream ostr;
    ostr << n << std::ends;
    Glib::ustring value(ostr.str().c_str());
    kf.insert_key_value(key, value);
  }
}


