/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team

This file is part of OpenMoHAA source code.

OpenMoHAA source code 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.

OpenMoHAA source code 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 OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
===========================================================================
*/

#include "ui_local.h"

CLASS_DECLARATION(UIWidget, UIChildSpaceWidget, NULL) {
    {NULL, NULL}
};

UIChildSpaceWidget::UIChildSpaceWidget() {}

qboolean UIChildSpaceWidget::KeyEvent(int key, unsigned int time)
{
    if (m_parent) {
        //
        // Transmit the key event to the parent
        //
        return m_parent->KeyEvent(key, 0);
    }

    return qfalse;
}

CLASS_DECLARATION(UIWidget, UIFloatingWindow, NULL) {
    {&W_LeftMouseDown,                     &UIFloatingWindow::Pressed        },
    {&W_LeftMouseDragged,                  &UIFloatingWindow::Dragged        },
    {&W_LeftMouseUp,                       &UIFloatingWindow::Released       },
    {&UIFloatingWindow::W_ClosePressed,    &UIFloatingWindow::ClosePressed   },
    {&UIFloatingWindow::W_MinimizePressed, &UIFloatingWindow::MinimizePressed},
    {&W_SizeChanged,                       &UIFloatingWindow::SizeChanged    },
    {&W_Activated,                         &UIFloatingWindow::OnActivated    },
    {NULL,                                 NULL                              }
};

Event UIFloatingWindow::W_ClosePressed(
    "floatingwindow_close_pressed", EV_DEFAULT, NULL, NULL, "Signal that the window was closed"
);
Event UIFloatingWindow::W_MinimizePressed(
    "floatingwindow_minimize_pressed", EV_DEFAULT, NULL, NULL, "Signal that the window was minimized"
);

UIFloatingWindow::UIFloatingWindow()
{
    m_clickpoint  = UIPoint2D(-20.0, -20.0);
    m_isPressed   = false;
    m_minimized   = false;
    m_canactivate = true;
    m_clicktime   = -20000;
    // create buttons that compose a window
    m_closeButton    = new UIButton();
    m_minimizeButton = new UIButton();
    m_childspace     = new UIChildSpaceWidget();
}

UIFloatingWindow::~UIFloatingWindow() {}

void UIFloatingWindow::FrameInitialized(void)
{
    FrameInitialized(true);
}

void UIFloatingWindow::FrameInitialized(bool bHasDragBar)
{
    //
    // Initialize the close button
    //
    m_closeButton->InitFrame(
        this,
        m_frame.size.width - 18.0 * getHighResScale()[0],
        2.0,
        16.0 * getHighResScale()[0],
        16.0 * getHighResScale()[1],
        -1,
        "marlett"
    );

    m_closeButton->setTitle("r");
    m_closeButton->setName("closebutton");

    //
    // Initialize the minimize button
    //
    m_minimizeButton->InitFrame(
        this,
        m_frame.size.width - 36.0 * getHighResScale()[0],
        2.0,
        16.0 * getHighResScale()[0],
        16.0 * getHighResScale()[1],
        -1,
        "marlett"
    );
    m_minimizeButton->setTitle("0");
    m_minimizeButton->setName("minimizebutton");

    m_closeButton->Connect(this, W_Button_Pressed, UIFloatingWindow::W_ClosePressed);
    m_minimizeButton->Connect(this, W_Button_Pressed, UIFloatingWindow::W_MinimizePressed);
    //
    // Size event
    //
    Connect(this, W_SizeChanged, W_SizeChanged);
    Connect(this, W_Activated, W_Activated);

    //
    // Child space
    //
    if (bHasDragBar) {
        m_childspace->InitFrame(
            this,
            UIRect2D(
                2.0,
                20.0 * getHighResScale()[1],
                m_frame.size.width - 4.0,
                m_frame.size.height - 22.0 * getHighResScale()[1]
            ),
            0,
            "verdana-12"
        );
    } else {
        m_childspace->InitFrame(this, UIRect2D(UIPoint2D(0, 0), m_frame.size), 0, "verdana-12");
    }

    m_childspace->setTitle("Child space");
    m_childspace->AllowActivate(true);
}

void UIFloatingWindow::ClosePressed(Event *ev)
{
    PostEvent(EV_Remove, 0.0);
}

void UIFloatingWindow::MinimizePressed(Event *ev)
{
    UISize2D size = getSize();

    if (!m_minimized) {
        m_minimized = true;
        // save the hold height
        // so the window can be restored later
        m_restoredHeight = size.height;
        size.height      = 20.0 * getHighResScale()[1];
        m_minimizeButton->setTitle("1");
    } else {
        m_minimized = false;
        size.height = m_restoredHeight;
        m_minimizeButton->setTitle("0");
    }

    setSize(size);
    uWinMan.ActivateControl(this);
}

void UIFloatingWindow::Pressed(Event *ev)
{
    UIPoint2D p = MouseEventToClientPoint(ev);

    m_clickOffset.x = p.x;
    m_clickOffset.y = p.y;

    if (uid.time - 500 >= m_clicktime) {
        m_clicktime = uid.time;
    } else {
        if (fabs(m_clickpoint.x - m_clickOffset.x) > 2.0 || fabs(m_clickpoint.y - m_clickOffset.y) > 2.0) {
            m_clicktime = uid.time;
        } else {
            ProcessEvent(W_MinimizePressed);
            m_clicktime = -20000;
        }
    }

    m_clickpoint = m_clickOffset;
    if (m_clickOffset.y < 18.0) {
        uWinMan.setFirstResponder(this);
        m_isPressed = true;
    }
}

void UIFloatingWindow::Released(Event *ev)
{
    if (!m_isPressed) {
        return;
    }

    uWinMan.setFirstResponder(NULL);
    m_isPressed = false;
    OnActivated(NULL);
}

void UIFloatingWindow::Dragged(Event *ev)
{
    if (!m_isPressed) {
        return;
    }

    UIPoint2D point = MouseEventToClientPoint(ev);
    UIPoint2D newpos;

    newpos.x = point.x - m_clickOffset.x;
    newpos.y = point.y - m_clickOffset.y;
    newpos.x += m_frame.pos.x;
    newpos.y += m_frame.pos.y;

    setFrame(UIRect2D(newpos, getSize()));
}

void UIFloatingWindow::SizeChanged(Event *ev)
{
    UIRect2D childRect;
    childRect.pos.x       = 2.0;
    childRect.pos.y       = 20.0 * getHighResScale()[1];
    childRect.size.width  = m_frame.size.width - 4.0 * getHighResScale()[0];
    childRect.size.height = m_frame.size.height - 22.0 * getHighResScale()[1];

    if (childRect.size.width <= 0.0 || childRect.size.height <= 0.0) {
        return;
    }

    m_childspace->setFrame(childRect);
    m_closeButton->setFrame(UIRect2D(
        m_frame.size.width - 18.0 * getHighResScale()[0], 2.0, 16.0 * getHighResScale()[0], 16.0 * getHighResScale()[1]
    ));
    m_minimizeButton->setFrame(UIRect2D(
        m_frame.size.width - 36.0 * getHighResScale()[0], 2.0, 16.0 * getHighResScale()[0], 16.0 * getHighResScale()[1]
    ));
}

void UIFloatingWindow::OnActivated(Event *ev)
{
    UIWidget *next;

    if (!IsActive()) {
        return;
    }

    for (next = m_childspace->getFirstChild(); next; next = m_childspace->getNextChild(next)) {
        if (next->CanActivate()) {
            uWinMan.ActivateControl(next);
            break;
        }
    }
}

void UIFloatingWindow::OnDeactivated(Event *ev)
{
    PostEvent(EV_Remove, 0.0);
}

void UIFloatingWindow::Create(
    UIWidget *parent, const UIRect2D& rect, const char *title, const UColor& bgColor, const UColor& fgColor
)
{
    m_titleColor = bgColor;
    m_textColor  = fgColor;
    setTitle(title);
    // actually create the window
    InitFrame(parent, rect.pos.x, rect.pos.y, rect.size.width, rect.size.height, 0, "verdana-14");
}

void UIFloatingWindow::Draw(void)
{
    UColor       titleBar;
    UColor       textColor;
    UBorderColor titleBorder;
    UBorderColor windowBorder;

    if (IsThisOrChildActive()) {
        UColor newColor;

        titleBar  = m_titleColor;
        textColor = m_textColor;

        UColorHSV tmp(titleBar);
        tmp.s *= 0.75;
        tmp.v *= 1.333;
        newColor = tmp;

        titleBorder.dark       = newColor;
        titleBorder.reallydark = newColor;
        titleBorder.light      = newColor;

    } else {
        UColor newColor(0.1125, 0.147, 0.2085, 1.0);

        titleBar  = newColor;
        textColor = UBlack;

        titleBorder.CreateSolidBorder(newColor, DARK);
        titleBorder.reallydark = newColor;
        titleBorder.light      = newColor;
    }

    UColor newColor(0.15, 0.196, 0.278, 1.0);
    newColor.ScaleColor(0.666f);

    windowBorder.dark       = newColor;
    windowBorder.reallydark = newColor;
    windowBorder.light      = newColor;

    setForegroundColor(textColor);
    m_closeButton->setForegroundColor(textColor);
    m_closeButton->setBackgroundColor(titleBar, true);
    m_minimizeButton->setForegroundColor(textColor);
    m_minimizeButton->setBackgroundColor(titleBar, true);

    if (!IsMinimized()) {
        DrawBoxWithSolidBorder(
            getClientFrame(), UColor(0.15, 0.195, 0.278, 1.0), UColor(0.075, 0.097, 0.139, 1.0), 2, 2, 1.0
        );
    }

    const float maxTitleBarHeight = 20 * getHighResScale()[1];

    DrawBox(
        0.0,
        0.0,
        m_frame.size.width,
        m_frame.size.height > maxTitleBarHeight ? maxTitleBarHeight : m_frame.size.height,
        titleBar,
        1.0
    );

    Draw3DBox(
        0.0,
        0.0,
        m_frame.size.width,
        m_frame.size.height > maxTitleBarHeight ? maxTitleBarHeight : m_frame.size.height,
        false,
        titleBorder,
        1.0
    );

    DrawTitle(3.0, 3.0);
}

UIChildSpaceWidget *UIFloatingWindow::getChildSpace(void)
{
    return m_childspace;
}

bool UIFloatingWindow::IsMinimized(void)
{
    return m_minimized;
}
