/*
 *  mdc_selection.h
 *  mdcanvas
 *
 *  Created by Alfredo Kojima on 07/Mar/14.
 *  Copyright 2007 MySQL AB. All rights reserved.
 *
 */

#ifndef _MDC_SELECTION_H_
#define _MDC_SELECTION_H_

#include "mdc_canvas_public.h"

#include "mdc_common.h"

#ifdef _WIN32
#include <hash_set>
#else
#include <ext/hash_set>
#include <set>
#endif

BEGIN_MDC_DECLS

class CanvasView;
class CanvasItem;

class MYSQLCANVAS_PUBLIC_FUNC Selection {
public:
  #ifdef _WIN32
  typedef stdext::hash_set<CanvasItem*> ContentType;
  #else
    //#ifdef __USE_GNU
    //typedef __gnu_cxx::hash_set<CanvasItem*> ContentType;
    typedef std::set<CanvasItem*> ContentType;
    //#endif
  #endif
  
  Selection(CanvasView *view);
  ~Selection();

  void set(CanvasItem *item);
  void add(CanvasItem *item);
  void remove(CanvasItem *item);
  void toggle(CanvasItem *item);

  void add(const std::list<CanvasItem*> &items);
  void toggle(const std::list<CanvasItem*> &items);

  void remove_items_outside(const Rect &rect);
  
  void clear(bool keep_move_info= false);

  void begin_multi_selection();
  void end_multi_selection();

  void begin_moving(const Point &mouse_pos);
  void update_move(const Point &mouse_pos);
  void end_moving();
  bool is_moving();

  ContentType get_contents() { return _items; };
  bool empty() const { return _items.empty(); };

  sigc::signal<void, bool, mdc::CanvasItem*> signal_changed() const { return _signal_changed; }
  sigc::signal<void> signal_begin_dragging() const { return _signal_begin_drag; }
  sigc::signal<void> signal_end_dragging() const { return _signal_end_drag; }

private:
  struct DragData 
  {
    Point offset;
    Point position;
    //Surface *image;

    //DragData() : image(0) {}
    //DragData(const DragData &other) : offset(other.offset), image(other.image ? new Surface(other.image->get_surface()) : 0) {}
    //~DragData() { delete image; }

    DragData &operator=(const DragData &other)
    {
      offset= other.offset;
      position= other.position;
      //image= 0;
      //if (other.image)
       // image= new Surface(other.image->get_surface());
      return *this;
    }
  };

  ContentType _items;

  ContentType _old_state;
  ContentType _current_selection;

  sigc::signal<void> _signal_begin_drag;
  sigc::signal<void> _signal_end_drag;

  std::map<CanvasItem*, DragData> _drag_data;
  GStaticRecMutex _mutex;
  CanvasView *_view;
  
  void lock();
  void unlock();

  //void render_drag_images(CairoCtx *cr);

  sigc::signal<void, bool, mdc::CanvasItem*> _signal_changed;
  int _block_signals;
};


END_MDC_DECLS

#endif
