/**
 @file HUDUI.cpp

 Dojo Game Engine

 Copyright 2005, Morgan McGuire
 All rights reserved.
 */

#include "dojo/DApp.h"
#include "dojo/HUDUI.h"
#include "dojo/G3UI.h"

namespace dojo {

HUDUI::HUDUI() : inDrag(false), processMouseDown(true) {
//    windowStack.push(Window::fromType(Window::WINDOW_GRAPHICS, this));
//    windowStack.push(Window::fromType(Window::WINDOW_PHYSICS, this));
    windowStack.push(NULL);

    {
        float w = 800;//app->window()->width();
        Vector2 c(w - 100, 50);
        Vector2 sz(200, 60);
        timeWindow = Rect2D::xywh(c - sz/2, sz);
    }
}


int HUDUI::windowIndex(Window::Type t) const {
    for (int w = 0; w < windowStack.size(); ++w) {
        if ((windowStack[w] != NULL) &&
            (windowStack[w]->type() == t)) {
            return w;
        }
    }

    return -1;
}

void HUDUI::loadData(DApp* _app, GFontRef _smallFont) {

    app = _app;
    smallFont = _smallFont;

    if (fileExists("dominant.fnt")) {
        labelFont = GFont::fromFile(NULL, "dominant.fnt");
    } else {
        labelFont = smallFont;
    }

    if (fileExists("play.ico")) {
        playIcon = Texture::fromFile("play.ico", TextureFormat::RGBA8, Texture::CLAMP);
    }

    if (fileExists("pause.ico")) {
        pauseIcon = Texture::fromFile("pause.ico", TextureFormat::RGBA8, Texture::CLAMP);
    }

    if (fileExists("step.ico")) {
        stepIcon = Texture::fromFile("step.ico", TextureFormat::RGBA8, Texture::CLAMP);
    }
}


void HUDUI::onGraphics(RenderDevice* rd) {
    rd->push2D();

        drawTimeBreakdown(timeWindow.center(), 30);

        rd->setBlendFunc(RenderDevice::BLEND_SRC_ALPHA, RenderDevice::BLEND_ONE_MINUS_SRC_ALPHA);
        rd->setAlphaTest(RenderDevice::ALPHA_GREATER, 0.0);

        for (int i = 0; i < windowStack.size(); ++i) {
            if (windowStack[i] != NULL) {
                windowStack[i]->draw(i == windowStack.size() - 1);
            }
        }
        
    rd->pop2D();
}


void HUDUI::onUserInput(UserInput* ui) {
    const Vector2 mouse = ui->mouseXY();

    if (inDrag) {
        Window* w = windowStack.last();
        debugAssert(w != NULL);

        float xx = w->rect.width();
        float yy = w->rect.height();
    
        // Clamp to screen
        Vector2 v = mouse + dragOffset;
        v = v.clamp(
            Vector2(0, 0), 
            Vector2(app->renderDevice->getWidth() - xx, 
                    app->renderDevice->getHeight() - yy));

        w->rect = Rect2D::xywh(v, Vector2(xx, yy));

        if (ui->keyReleased(G3D::SDL_LEFT_MOUSE_KEY)) {
            // End the drag
            inDrag = false;
            processMouseDown = true;
            // Don't handle any other events on the cycle when we release.
            return;
        }
    }
    
    if (processMouseDown && ui->keyPressed(G3D::SDL_LEFT_MOUSE_KEY)) {
        // Mouse down

        bool inWindow = false;

        // Work back from the topmost window
        for (int i = windowStack.size() - 1; i >= 0; --i) {
            if ((windowStack[i] != NULL) && (windowStack[i]->rect.contains(mouse))) {
                // Found window containing mouse
                if (windowStack.last() == NULL) {
                    // There was no active window.
                    windowStack.pop();
                }

                if (i != windowStack.size() - 1) {
                    // Move this window to the top of the stack
                    Window* cur = windowStack[i];
                    windowStack.remove(i);
                    windowStack.append(cur);
                }

                inWindow = true;
                break;
            }
        }

        if (! inWindow) {
            // Not in any window. Deactivate the topmost window if it
            // is active (not NULL).
            if (windowStack.last() != NULL) {
                windowStack.append(NULL);
            }
        }

        if (windowStack.last() != NULL) {
            // If there is an active window, process the click

            Window* w = windowStack.last();

            // Some click inside the current window
            // TODO: move this handler code to the window class
            if (G3UI::inCloseButton(mouse, w->rect)) {
                delete w;
                w = NULL;
                windowStack.popDiscard();
                // No active window
                windowStack.push(NULL);
            } else if (G3UI::inWindowTitleBar(mouse, w->rect)) {
                inDrag = true;
                processMouseDown = false;
                dragOffset = w->rect.x0y0() - mouse;
            }
        } else if (timeWindow.contains(mouse)) {
            // Figure out which button the user clicked on
            Rect2D rect = 
                Rect2D::xywh(timeWindow.x0(), timeWindow.y0() + 2.5, 75, 12);

            // Order of windows on the time display
            Window::Type buttonMapping[6] = 
                {Window::WINDOW_NONE, Window::WINDOW_NONE, Window::WINDOW_PHYSICS, 
                Window::WINDOW_GRAPHICS, Window::WINDOW_NONE, Window::WINDOW_NONE};

            for (int i = 0; i < 6; ++i) {
                Rect2D button = rect + Vector2((i / 3) * 125, (i % 3) * 19.5);
                if (button.contains(mouse)) {
                    // Clicked on a button


                    Window::Type type = buttonMapping[i];
                    if (type != Window::WINDOW_NONE) {
                        // Make sure there is some active window
                        if (windowStack.last() == NULL) {
                            windowStack.popDiscard();
                        }

                        int w = windowIndex(type);
                        if (w == -1) {
                            // Create a new window and make it active
                            windowStack.push(Window::fromType(type, this));
                        } else {
                            // Pop previously existing window to the top
                            Window* temp = windowStack[w];
                            windowStack[w] = windowStack.last();
                            windowStack.last() = temp;
                        }
                    }
                    break;
                }           
            }
        }
    }
}


}
