// src/testsuite/test-stepforward.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

/* This executable tests for workingness of the stepForward method,
 * and nothing else. */



#include <glibmm/module.h> // ??
#include <cassert>
#include <string>
#include "config.h"
#include "gettext.h"
#include "glibmm/ustring.h"
#include <vector>
#include <iostream>
#include "backend/static_process.hh"
#include "backend/observed_subject.hh"
#include <sgpemv2/ready_queue.hh>
#include "backend/dynamic_schedulable.hh"

#include <sgpemv2/scheduler.hh>
#include <sgpemv2/user_interrupt_exception.hh>

#include <sgpemv2/templates/smartp.tcc>

#include <iostream>


namespace sgpem
{
  /** An hard-coded Priority Round Robin policy
   * It's actually called PRRPolicy, altough my personal taste would have suggested 
   * naming it 
   * Prioriy-Reliant Roughly-Realized Recently-Reimplemented Round-Robin Policy, 
   * i.e. PRRRRRRR-Policy.
   * it adds a new constructor taking the quantum size (time slice)*/

  class PRRPolicy : public Policy
  {
  public:

    Policy()
    {
      _instance = this;
    }

    Policy(int quantum) : _quantum(quantum)
    {
      _instance = this;
    }

    static Policy& get_instance()
    {
      if (!_instance) _instance = new Policy(3); // quantum size
      return *_instance;
    }

    virtual ~Policy()
  {}

    virtual void configure()
    {}

    virtual void sort_queue() const throw(UserInterruptException)
    { // here a lot of fun, exactly O(n^2) fun!
      ReadyQueue sl = History.get_instance().get_simulation_status_at(get_current_time());
      for (int i = 0; i < sl.size(); i++)
      {
        for (int j = 0; j < sl.size() - 1; j++)
        {
          if (sl.get_item_at(j).get_schedulable().get_priority() < sl.get_item_at(j + 1).get_schedulable().get_priority())
          {
            sl.swap(j, j + 1);
          }
        }

      }
    }

    int get_id() const
    {
      return 42;
    }

    virtual Glib::ustring get_description()
    {
      return "42";
    }
    virtual bool is_pre_emptive() const throw(UserInterruptException)
    {
      return 1;
    }
    virtual int get_time_slice() const throw(UserInterruptException)
    {
      return _quantum;
    }

    PolicyParameters& get_parameters()
    {
      return _parameters;
    }


  protected:

    PolicyParameters _parameters;
    int _id;
    int _quantum;

  private:

    static Policy* _instance;
  };

  Policy*
  PRRPolicy::_instance = NULL;




  // A PolicyManager stub
  class PolicyManager
  {
  public:

    PolicyManager();
    virtual ~PolicyManager();
    virtual Policy& get_policy()
    {
      return PRRPolicy.get_instance();
    }
    virtual void init()
    {}
    static PolicyManager& get_registered_manager();

  private:

    static PolicyManager* _registered;
  };

  PolicyManager*
  PolicyManager::_registered = NULL;

  PolicyManager::PolicyManager()
  {
    _registered = this;
  }


  PolicyManager::~PolicyManager()
  {
    if (_registered == this) _registered = NULL;
  }

  PolicyManager&
  PolicyManager::get_registered_manager()
  {
    return *_registered;
  }



  // a History stub, should only save the last state included. but...
  class History : public ObservedSubject
  {
  public:

    memory::smart_ptr<sgpem::DynamicSchedulable> get_scheduled_at(int time) const {}
    memory::smart_ptr<sgpem::ReadyQueue> get_simulation_status_at(int time) const;
    int get_current_time() const {return _total_time_elapsed;}
    void enqueue_slice(const sgpem::ReadyQueue& status);
    void truncate_at(int instant) {}
    static History& get_instance();
  private:
    History(int);   //private constructor. The parameter is discarded
    static History  _instance;
    int             _total_time_elapsed;
    std::vector<sgpem::Slice> _slices;
  };
  History&
  History::get_instance()

  {
    if (!_instance) _instance = new Policy(3); // quantum size
    return *_instance;
  }




} //~ namespace sgpem



// this class should invoke the Scheduler Stepforward method.
class StepForwardTester
{
}

// from here and further until the bottom, all to throw away I suppose

int
main(int argc, char** argv)
{

  using namespace sgpem;
  using Glib::Module;


  std::string command(ERERERT); // the sequence of commands to test

  // sets up the test data
  StaticProcess p1("P1", 1, 5, 1);
  StaticProcess p2("P2", 5, 55, 2);
  StaticProcess p3("P3", 36, 30, 3);
  StaticProcess p4("P4", 4, 26, 3);
  StaticProcess p5("P5", 15, 200, 3);
  StaticProcess p6("P6", 6, 250, 1);
  StaticProcess p7("P7", 8, 42, 15);
  StaticProcess p8("P8", 8, 56, 1);
  StaticProcess p9("P9", 9, 42, 1);
  StaticProcess p10("PA", 12, 42, 1);
  StaticProcess p11("PB", 106, 42, 1);
  StaticProcess p12("PC", 100, 42, 1);
  StaticProcess p13("PD", 29, 42, 18);
  StaticProcess p14("PE", 0, 42, 1);
  StaticProcess p15("PF", 2, 88, 1);
  StaticProcess p16("PG", 3666, 9, 1);
  StaticProcess p17("PH", 5, 72, 10);
  StaticProcess p18("PJ", 6, 26, 1);
  StaticProcess p19("PK", 10, 24, 17);
  StaticProcess p20("PK2", 11, 34, 67); // not used!

  DynamicSchedulable ss1(p1);
  DynamicSchedulable ss2(p2);
  DynamicSchedulable ss3(p3);
  DynamicSchedulable ss4(p4);
  DynamicSchedulable ss5(p5);
  DynamicSchedulable ss6(p6);
  DynamicSchedulable ss7(p7);
  DynamicSchedulable ss8(p8);
  DynamicSchedulable ss9(p9);
  DynamicSchedulable ss10(p10);
  DynamicSchedulable ss11(p11);
  DynamicSchedulable ss12(p12);
  DynamicSchedulable ss13(p13);
  DynamicSchedulable ss14(p14);
  DynamicSchedulable ss15(p15);
  DynamicSchedulable ss16(p16);
  DynamicSchedulable ss17(p17);
  DynamicSchedulable ss18(p18);
  DynamicSchedulable ss19(p19); // not used!

  ReadyQueue initial;
  initial.add_at_bottom(ss1);
  initial.add_at_bottom(ss2);
  initial.add_at_bottom(ss3);
  initial.add_at_bottom(ss4);
  initial.add_at_bottom(ss5);
  initial.add_at_bottom(ss6);
  initial.add_at_bottom(ss7);
  initial.add_at_bottom(ss8);
  initial.add_at_bottom(ss9);
  initial.add_at_bottom(ss10);
  initial.add_at_bottom(ss11);
  initial.add_at_bottom(ss12);
  initial.add_at_bottom(ss13);
  initial.add_at_bottom(ss14);
  initial.add_at_bottom(ss15);
  initial.add_at_bottom(ss16);
  initial.add_at_bottom(ss17);
  initial.add_at_bottom(ss18);

  HistoryTester HT(initial);
  HT.test("ERERERERTTTETRERERETETTTTTTTTTTTTTT");


  exit(0);
}
