#ifndef __Window__
#define __Window__

#ifndef GUI_DLL 
    #ifdef GUI_BUILD
	    #define GUI_DLL __declspec(dllexport)
    #else
	    #define GUI_DLL __declspec(dllimport)
        #pragma comment(lib, "WindowManager.lib")
    #endif
#endif

#include "../Core/types.h"
#include "../Core/SceneGraph/Sprite.h"
#include "../Core/SceneGraph/Text.h"
#include "../Core/ResourceManager.h"
#include "Event.h"

#include <FastDelegate.h>
#include <map>



class GUI_DLL Point {
public:
    Point(float x = 0.0f, float y = 0.0f) : _x(x), _y(y) {}
    Point(Point& other) : _x(other._x), _y(other._y) {}

    float& x() { return _x; }
    float& y() { return _y; }

    Point& operator+=(Point& other) {
        _x += other._x;
        _y += other._y;
        return *this;
    }

    Point operator+(Point& other) {
        return Point(*this) += other;
    }

    Point& operator-=(Point& other) {
        _x -= other._x;
        _y -= other._y;
        return *this;
    }

    Point operator-(Point& other) {
        return Point(*this) -= other;
    }

protected:
    float _x, _y;
};

class GUI_DLL Size {
public:
    Size(float w = 0.0f, float h = 0.0f) : _w(w), _h(h) {}
    Size(Size& other) : _w(other._w), _h(other._h) {}

    float& w() { return _w; }
    float& h() { return _h; }

protected:
    float _w, _h;
};



#pragma warning(push)
#pragma warning(disable:4251)

class Window;
typedef void (Window::*EventHandler)(Event&);
typedef fastdelegate::FastDelegate1<Event&> EventHandlerDelegate;


class GUI_DLL Window : public Sprite {
public:
    Window(Window* parent = 0);
    virtual ~Window();

    Point getPosition();
    Size  getSize();

    virtual void setPosition(Point& position);
    virtual void setSize(Size& size);

    virtual void addChild(Window* child);
    virtual void removeChild(Window* child);

    virtual Text* getCaption();
    virtual void setCaption(const wchar_t* caption);

    virtual bool isHit(float x, float y);
    virtual Window* getHitWindow(float x, float y);

    void connectEvent(int eventType, Window* window, EventHandler eventHandler);
    void disconnectEvent(int eventType, Window* window, EventHandler eventHandler);

    void handleEvent(Event& event);

    bool  isEnabled();
    virtual void enable(bool enabled);

    bool  isDraggable();
    virtual void setDraggable(bool draggable);

    bool  isDragBound();
    virtual void setDragBound(bool dragBound);

    Window* getParent();
    virtual void setParent(Window* parent);

    Point getTranslatedPosition();


protected:

    Window* _parent;

    Text*   _caption;

    Point _position;
    Size  _size;

    bool  _enabled;
    bool  _draggable;
    bool  _dragBound;

    std::multimap<int, EventHandlerDelegate> _eventHandlers;
};

#pragma warning(pop)

#endif