#include "Dialog.h"


class Dialog::Tray {
    friend class Dialog;
public:
    Tray(Dialog* parent);
    virtual ~Tray();
    
    void resize();
    void activate(bool active);

protected:
    class TrayLeft : public Window {
        friend class Dialog;
    public:
        TrayLeft(Window* parent);
        virtual ~TrayLeft();

        void activate(bool active);

    protected:
        void onBeginDrag(Event& event);
        void onDrag(Event& event);

        Point _parentPosition;

        Texture* _inactiveTexture;
        Texture* _activeTexture;
    };

    class TrayMiddle : public Window  {
        friend class Dialog;
    public:
        TrayMiddle(Window* parent);
        virtual ~TrayMiddle();

        void activate(bool active);

    protected:
        void onBeginDrag(Event& event);
        void onDrag(Event& event);

        Point _parentPosition;

        Texture* _inactiveTexture;
        Texture* _activeTexture;
    };

    class TrayRight : public Window  {
        friend class Dialog;
    public:
        TrayRight(Window* parent);
        virtual ~TrayRight();

        void activate(bool active);

    protected:
        void onBeginDrag(Event& event);
        void onDrag(Event& event);

        Point _parentPosition;

        Texture* _inactiveTexture;
        Texture* _activeTexture;
    };

    TrayLeft*   _trayLeft;
    TrayMiddle* _trayMiddle;
    TrayRight*  _trayRight;

    Dialog*     _parent;
};

Dialog::Tray::Tray(Dialog* parent)
: _parent(parent), _trayLeft(0), _trayMiddle(0), _trayRight(0)
{
    _trayLeft   = new TrayLeft(_parent);
    _trayMiddle = new TrayMiddle(_parent);
    _trayRight  = new TrayRight(_parent);
}

Dialog::Tray::~Tray()
{
    delete _trayLeft;
    delete _trayMiddle;
    delete _trayRight;
}

void Dialog::Tray::resize()
{
    Size dialogSize = _parent->getSize();

    _trayLeft->setSize(Size(8, 24.0f));
    _trayLeft->setPosition(Point(-4.0f, -24.0f));

    _trayMiddle->setSize(Size(dialogSize.w() - 8.0f, 24.0f));
    _trayMiddle->setPosition(Point(4.0f, -24.0f));

    _trayRight->setSize(Size(8, 24.0f));
    _trayRight->setPosition(Point(dialogSize.w() - 4.0f, -24.0f));
}

void Dialog::Tray::activate(bool active)
{
    _trayLeft->activate(active);
    _trayMiddle->activate(active);
    _trayRight->activate(active);
}

Dialog::Tray::TrayLeft::TrayLeft(Window* parent)
: Window(parent), _inactiveTexture(0), _activeTexture(0)
{
    setPosition(Point(-4.0f, -24.0f));
    setSize(Size(8.0f, 24.0f));

    _inactiveTexture = ResourceManager::instance().loadTexture(L"textures/gui/dialog_tray_left_inactive.dds");
    _activeTexture = ResourceManager::instance().loadTexture(L"textures/gui/dialog_tray_left.dds");

    _texture = _inactiveTexture;

    _draggable = true;
    _dragBound = false;

    connectEvent(Event::DRAG_BEGIN, this, (EventHandler)&Dialog::Tray::TrayLeft::onBeginDrag);
    connectEvent(Event::DRAG,       this, (EventHandler)&Dialog::Tray::TrayLeft::onDrag);
}

Dialog::Tray::TrayLeft::~TrayLeft()
{
}

void Dialog::Tray::TrayLeft::onBeginDrag(Event& event)
{
    _parentPosition = _parent->getPosition();
}

void Dialog::Tray::TrayLeft::onDrag(Event& event)
{
    Point offset = _position;
    offset.x() += 4.0f;
    offset.y() += 24.0f;

    _parent->setPosition(_parentPosition + offset);
    setPosition(Point(-4.0f, -24.0f));
}

void Dialog::Tray::TrayLeft::activate(bool active)
{
    if (active)
        _texture = _activeTexture;
    else
        _texture = _inactiveTexture;
}

Dialog::Tray::TrayMiddle::TrayMiddle(Window* parent)
: Window(parent), _inactiveTexture(0), _activeTexture(0)
{
    Size parentSize = parent->getSize();

    setPosition(Point(4.0f, -24.0f));
    setSize(Size(parentSize.w() - 8.0f, 24.0f));

    _inactiveTexture = ResourceManager::instance().loadTexture(L"textures/gui/dialog_tray_middle_inactive.dds");
    _activeTexture = ResourceManager::instance().loadTexture(L"textures/gui/dialog_tray_middle.dds");

    _texture = _inactiveTexture;

    _draggable = true;
    _dragBound = false;

    _caption->setFont(L"Microsoft Sans Serif", L"ffffff", 15.0f, Text::FONT_STYLE_BOLD, Text::H_ALIGN_CENTER | Text::V_ALIGN_CENTER);

    connectEvent(Event::DRAG_BEGIN, this, (EventHandler)&Dialog::Tray::TrayMiddle::onBeginDrag);
    connectEvent(Event::DRAG,       this, (EventHandler)&Dialog::Tray::TrayMiddle::onDrag);
}

Dialog::Tray::TrayMiddle::~TrayMiddle()
{
}

void Dialog::Tray::TrayMiddle::onBeginDrag(Event& event)
{
    _parentPosition = _parent->getPosition();
}

void Dialog::Tray::TrayMiddle::onDrag(Event& event)
{
    Point offset = _position;
    offset.x() -= 4.0f;
    offset.y() += 24.0f;

    _parent->setPosition(_parentPosition + offset);
    setPosition(Point(4.0f, -24.0f));
}

void Dialog::Tray::TrayMiddle::activate(bool active)
{
    if (active)
        _texture = _activeTexture;
    else
        _texture = _inactiveTexture;
}

Dialog::Tray::TrayRight::TrayRight(Window* parent)
: Window(parent), _inactiveTexture(0), _activeTexture(0)
{
    Size parentSize = parent->getSize();

    setPosition(Point(parentSize.w() - 4.0f, -24.0f));
    setSize(Size(8.0f, 24.0f));

    _inactiveTexture = ResourceManager::instance().loadTexture(L"textures/gui/dialog_tray_right_inactive.dds");
    _activeTexture = ResourceManager::instance().loadTexture(L"textures/gui/dialog_tray_right.dds");

    _texture = _inactiveTexture;

    _draggable = true;
    _dragBound = false;

    connectEvent(Event::DRAG_BEGIN, this, (EventHandler)&Dialog::Tray::TrayRight::onBeginDrag);
    connectEvent(Event::DRAG,       this, (EventHandler)&Dialog::Tray::TrayRight::onDrag);
}

Dialog::Tray::TrayRight::~TrayRight()
{
}

void Dialog::Tray::TrayRight::onBeginDrag(Event& event)
{
    _parentPosition = _parent->getPosition();
}

void Dialog::Tray::TrayRight::onDrag(Event& event)
{
    Size parentSize = _parent->getSize();

    Point offset = _position;
    offset.x() -= parentSize.w() - 4.0f;
    offset.y() += 24.0f;

    _parent->setPosition(_parentPosition + offset);
    setPosition(Point(parentSize.w() - 4.0f, -24.0f));
}

void Dialog::Tray::TrayRight::activate(bool active)
{
    if (active)
        _texture = _activeTexture;
    else
        _texture = _inactiveTexture;
}




class Dialog::VerticalFrame : public Window {
public:
    VerticalFrame(Window* parent);
    virtual ~VerticalFrame();

    void activate(bool active);

protected:
    Texture* _activeTexture;
    Texture* _inactiveTexture;
};

Dialog::VerticalFrame::VerticalFrame(Window* parent)
: Window(parent), _activeTexture(0), _inactiveTexture(0)
{
    Size parentSize = _parent->getSize();

    setPosition(Point(-4.0f, 0.0f));
    setSize(Size(4.0f, parentSize.h() + 4.0f));
    
    _activeTexture   = ResourceManager::instance().loadTexture(L"textures/gui/frame_v.dds");
    _inactiveTexture = ResourceManager::instance().loadTexture(L"textures/gui/frame_v_inactive.dds");

    _texture = _inactiveTexture;
}

Dialog::VerticalFrame::~VerticalFrame()
{
}

void Dialog::VerticalFrame::activate(bool active)
{
    if (active)
        _texture = _activeTexture;
    else
        _texture = _inactiveTexture;
}



class Dialog::HorizontalFrame : public Window {
public:
    HorizontalFrame(Window* parent);
    virtual ~HorizontalFrame();

    void activate(bool active);

protected:
    Texture* _activeTexture;
    Texture* _inactiveTexture;
};

Dialog::HorizontalFrame::HorizontalFrame(Window* parent)
: Window(parent), _activeTexture(0), _inactiveTexture(0)
{
    Size parentSize = _parent->getSize();

    setPosition(Point(0.0f, parentSize.h()));
    setSize(Size(parentSize.w(), 4.0f));

    _activeTexture   = ResourceManager::instance().loadTexture(L"textures/gui/frame_h.dds");
    _inactiveTexture = ResourceManager::instance().loadTexture(L"textures/gui/frame_h_inactive.dds");

    _texture = _inactiveTexture;
}

Dialog::HorizontalFrame::~HorizontalFrame()
{
}

void Dialog::HorizontalFrame::activate(bool active)
{
    if (active)
        _texture = _activeTexture;
    else
        _texture = _inactiveTexture;
}



Dialog::Dialog(Window* parent)
: Window(parent), _tray(0), _leftFrame(0), _rightFrame(0), _bottomFrame(0)
{
    setPosition(Point(0.0f, 0.0f));
    setSize(Size(480.0f, 640.0f));

    _texture = ResourceManager::instance().loadTexture(L"textures/gui/window.dds");

    _tray = new Tray(this);
    _leftFrame = new VerticalFrame(this);
    _rightFrame = new VerticalFrame(this);
    _bottomFrame = new HorizontalFrame(this);

    _rightFrame->setPosition(Point(_size.w(), 0.0f));

    connectEvent(Event::FOCUS_GAINED, this, (EventHandler)&Dialog::onGainFocus);
    connectEvent(Event::FOCUS_LOST,   this, (EventHandler)&Dialog::onLoseFocus);
}

Dialog::~Dialog()
{
    delete _tray;
    delete _leftFrame;
    delete _rightFrame;
    delete _bottomFrame;
}

void Dialog::setSize(Size& size)
{
    Window::setSize(size);

    if (_tray != 0) {
        _tray->resize();

        _leftFrame->setPosition(Point(-4.0f, 0.0f));
        _leftFrame->setSize(Size(4.0f, _size.h() + 4.0f));

        _rightFrame->setPosition(Point(_size.w(), 0.0f));
        _rightFrame->setSize(Size(4.0f, _size.h() + 4.0f));

        _bottomFrame->setPosition(Point(0.0f, _size.h()));
        _bottomFrame->setSize(Size(_size.w(), 4.0f));
    }
}

Text* Dialog::getCaption()
{
    return _tray->_trayMiddle->getCaption();
}

void Dialog::setCaption(const wchar_t* caption)
{
    _tray->_trayMiddle->setCaption(caption);
}

void Dialog::onGainFocus(Event& event)
{
    _tray->activate(true);
    _leftFrame->activate(true);
    _rightFrame->activate(true);
    _bottomFrame->activate(true);
}

void Dialog::onLoseFocus(Event& event)
{
    _tray->activate(false);
    _leftFrame->activate(false);
    _rightFrame->activate(false);
    _bottomFrame->activate(false);
}