// src/holt_widget.hh - 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

#ifndef HOLT_WIDGET_HH
#define HOLT_WIDGET_HH 1

#include "config.h"

#include "cairo_widget.hh"
#include <sgpemv2/history_observer.hh>
#include <sgpemv2/request.hh>
#include <sgpemv2/simulation_observer.hh>

#include <complex>


namespace sgpem
{
  class History;
  class Schedulable;
  class Resource;
}

namespace sgpem
{
  typedef SubRequest::resource_key_t     resource_key_t;

  /**
   * \brief Every point or vector is a Vec2.
   * This phisical vector class, Vec2 is realized trough
   * complex<double> because it's a full operative class with operators.
   */
  typedef std::complex<double> Vec2;


  class HoltNode
  {
  public:
    // HoltNode(double x=0.0, double y=0.0);
    HoltNode(Vec2 pt = Vec2(0.0, 0.0));
    virtual ~HoltNode();

    virtual void draw(cairo_t *cr) = 0;
    // void set_position(double x, double y);
    Vec2 set_position(Vec2 pt);
    Vec2 get_position();
    double set_radius(double radius);
    double get_radius();
    virtual Vec2 get_intersection_to(Vec2 pt) = 0;
  protected:
    double _radius;
    // double _x, _y;
    Vec2 _pos;
  private:
  };


  class HoltResource : public HoltNode
  {
  public:
    // HoltResource(const Resource& resource, resource_key_t resource_key, double x=0.0, double y=0.0);
    HoltResource(const Resource& resource, resource_key_t resource_key, Vec2 pt = Vec2(0.0, 0.0));
    virtual ~HoltResource();

    virtual void draw(cairo_t *cr);
    virtual Vec2 get_intersection_to(Vec2 pt);
  protected:
  private:
    const Resource* _resource;
    resource_key_t _resource_key;
  };


  class HoltSchedulable : public HoltNode
  {
  public:
    //HoltSchedulable(const Schedulable& schedulable, double x=0.0, double y=0.0);
    HoltSchedulable(const Schedulable& schedulable, Vec2 pt = Vec2(0.0, 0.0));
    virtual ~HoltSchedulable();

    virtual void draw(cairo_t *cr);
    virtual Vec2 get_intersection_to(Vec2 pt);
  protected:
  private:
    const Schedulable* _schedulable;
  };

  class HoltRequest
  {
  public:
    HoltRequest(HoltSchedulable& hp, HoltResource& hr, Request::state state);
    virtual ~HoltRequest();

    virtual void draw(cairo_t *cr);
    virtual void arrow(cairo_t *cr, Vec2 first, Vec2 second);
  protected:
  private:
    HoltSchedulable*   _hp;
    HoltResource*  _hr;
    Request::state _state;
  };




  class HoltWidget
  : public SimulationObserver,
  public HistoryObserver,
  public  CairoWidget
  {
  public:
    enum arrange_mode
    {
      arrange_horizontal  =  1 << 0,
      arrange_vertical    =  1 << 1,
      arrange_circular    =  1 << 2
    };

    typedef std::map<resource_key_t, HoltResource*>   HoltResources;
    typedef std::vector<HoltSchedulable*>                 HoltProcesses;
    typedef std::vector<HoltRequest*>                 HoltRequests;

    HoltWidget(Simulation& simulation);
    virtual ~HoltWidget();

    void update(const Simulation& changed_simulation);
    void update(const History& changed_history);
    void acquire();

    double get_radius();
    double set_radius(double radius);
    arrange_mode get_arrange_mode();
    arrange_mode set_arrange_mode(arrange_mode mode);
    void arrange();
    bool get_show_threads();
    bool set_show_threads(bool show);

  protected:

    void draw_widget(cairo_t* ctx);

    virtual void calc_drawing_size(cairo_t* ctx, size_t& width, size_t& height);
    virtual void calc_widget_size(size_t& width, size_t& height);

  private:
    // int _x_unit;
    //int _y_unit;
    Simulation* _simulation;
  
    double _radius;

    HoltResources _holt_resources;
    HoltProcesses _holt_schedulables;
    HoltRequests  _holt_requests;
    int           _n_proc;
    int           _n_res;

    arrange_mode  _arrange_mode;
    bool          _show_threads;
  };

} //~ namespace sgpem


#endif //~ HOLT_WIDGET_HH
