/*
===========================================================================
Copyright (C) 2015 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"
#include "../qcommon/localization.h"

Event W_Button_Pressed
(
    "button_pressed",
    EV_DEFAULT,
    NULL,
    NULL,
    "Signal that the button was pressed"
);

Event W_Button_HoverSound
(
    "hoversound",
    EV_DEFAULT,
    "s",
    "soundName",
    "Set the sound to play when this button is hovered over"
);

Event W_Button_HoverCommand
(
    "hovercommand",
    EV_DEFAULT,
    "s",
    "string",
    "Set the command to execute when this button is hovered over"
);

Event W_Button_MouseAwayCommand
(
    "mouseawaycommand",
    EV_DEFAULT,
    "s",
    "string",
    "Set the command to execute when the mouse exits this button"
);

CLASS_DECLARATION(UIWidget, UIButtonBase, NULL) {
    {&W_LeftMouseDown,           &UIButtonBase::Pressed              },
    {&W_LeftMouseUp,             &UIButtonBase::Released             },
    {&W_LeftMouseDragged,        &UIButtonBase::Dragged              },
    {&W_MouseEntered,            &UIButtonBase::MouseEntered         },
    {&W_MouseExited,             &UIButtonBase::MouseExited          },
    {&W_Button_HoverSound,       &UIButtonBase::SetHoverSound        },
    {&W_Button_HoverCommand,     &UIButtonBase::SetHoverCommand      },
    {&W_Button_MouseAwayCommand, &UIButtonBase::SetMouseExitedCommand},
    {NULL,                       NULL                                }
};

UIButtonBase::UIButtonBase()
{
    m_mouseState = M_NONE;
    AllowActivate(true);
}

void UIButtonBase::Pressed(Event *ev)
{
    m_mouseState             = M_DRAGGING;
    m_hovermaterial_active   = qtrue;
    m_pressedmaterial_active = qtrue;
    uWinMan.setFirstResponder(this);
}

void UIButtonBase::Released(Event *ev)
{
    if (m_mouseState != M_DRAGGING) {
        m_mouseState = M_NONE;
        return;
    }

    if (uWinMan.getFirstResponder() == this) {
        // make sure to not respond multiple times
        uWinMan.setFirstResponder(NULL);
    }

    m_mouseState = M_NONE;

    if (ev) {
        if (!getClientFrame().contains(MouseEventToClientPoint(ev))) {
            // not in the frame anymore
            m_hovermaterial_active   = false;
            m_pressedmaterial_active = false;
            return;
        }
    }

    Action();

    if (ev) {
        if (getClientFrame().contains(MouseEventToClientPoint(ev))) {
            // handle the button click
            SendSignal(W_Button_Pressed);
        }
    }
}

void UIButtonBase::MouseEntered(Event *ev)
{
    m_hovermaterial_active = qtrue;
    uWinMan.ActivateControl(this);

    if (m_hoverSound.length()) {
        uii.Snd_PlaySound(m_hoverSound.c_str());
    }

    if (m_hoverCommand.length()) {
        str stuff = m_hoverCommand + "\n";
        uii.Cmd_Stuff(stuff.c_str());
    }
}

void UIButtonBase::MouseExited(Event *ev)
{
    SetHovermaterialActive(false);

    if (m_mouseExitedCommand.length()) {
        str stuff = m_mouseExitedCommand + "\n";
        uii.Cmd_Stuff(stuff.c_str());
    }
}

void UIButtonBase::Dragged(Event *ev)
{
    SetHovermaterialActive(getClientFrame().contains(MouseEventToClientPoint(ev)));
}

void UIButtonBase::SetHoverSound(Event *ev)
{
    m_hoverSound = ev->GetString(1);
}

void UIButtonBase::SetHoverCommand(Event *ev)
{
    m_hoverCommand = ev->GetString(1);
}

void UIButtonBase::SetMouseExitedCommand(Event *ev)
{
    m_mouseExitedCommand = ev->GetString(1);
}

void UIButtonBase::Action(void)
{
    if (m_clicksound.length()) {
        uii.Snd_PlaySound(m_clicksound.c_str());
    }

    if (m_command.length()) {
        str stuff = m_command + "\n";
        uii.Cmd_Stuff(stuff.c_str());
    }
}

CLASS_DECLARATION(UIButtonBase, UIButton, NULL) {
    {NULL, NULL}
};

UIButton::UIButton()
{
    setBorderStyle(border_none);
}

void UIButton::Draw(void)
{
    if (m_mouseState == M_DRAGGING && m_screenframe.contains(uid.mouseX, uid.mouseY)) {
        DrawPressed();
    } else {
        DrawUnpressed();
    }
}

void UIButton::DrawPressed(void)
{
    UIRect2D clientFrame = getClientFrame();

    if (m_borderStyle != border_none) {
        Draw3DBox(clientFrame, true, m_border_color, m_local_alpha);
    }

    m_font->setColor(m_foreground_color);

    clientFrame.pos.x += 1;
    clientFrame.pos.y += 1;

    m_font->PrintJustified(
        clientFrame,
        m_iFontAlignmentHorizontal,
        m_iFontAlignmentVertical,
        Sys_LV_CL_ConvertString(m_title.c_str()),
        getVirtualScale()
    );
}

void UIButton::DrawUnpressed(void)
{
    m_font->setColor(m_foreground_color);
    m_font->setAlpha(m_local_alpha);

    UIRect2D clientFrame = getClientFrame();

    m_font->PrintJustified(
        clientFrame,
        m_iFontAlignmentHorizontal,
        m_iFontAlignmentVertical,
        Sys_LV_CL_ConvertString(m_title.c_str()),
        getVirtualScale()
    );
}

qboolean UIButton::KeyEvent(int key, unsigned int time)
{
    if (key != K_ENTER && key != K_KP_ENTER) {
        return false;
    }

    UIButtonBase::Action();
    return true;
}

CLASS_DECLARATION(USignal, ToggleCVar, NULL) {
    {NULL, NULL}
};

ToggleCVar::ToggleCVar()
{
    m_button = 0;
}

ToggleCVar::ToggleCVar(UIButton *button, const char *cvar)
    : ToggleCVar()
{
    setButton(button);

    if (cvar) {
        setCVar(cvar);
    }
}

void ToggleCVar::Press(Event *ev)
{
    if (m_cvarname.length()) {
        UI_SetCvarInt(m_cvarname.c_str(), UI_GetCvarInt(m_cvarname.c_str(), 0));
    }
}

void ToggleCVar::setCVar(const char *cvar)
{
    m_cvarname = cvar;
}

void ToggleCVar::setButton(UIButton *button)
{
    if (m_button) {
        m_button->Disconnect(this, W_Button_Pressed);
    }

    m_button = button;
    if (m_button) {
        m_button->Connect(this, W_Button_Pressed, W_Button_Pressed);
    }
}

CLASS_DECLARATION(USignal, ExecCmd, NULL) {
    {NULL, NULL}
};

ExecCmd::ExecCmd()
{
    m_button = NULL;
}

ExecCmd::ExecCmd(UIButton *button, const char *cmd)
    : ExecCmd()
{
    setButton(button);
    setCommand(cmd);
}

void ExecCmd::Press(Event *ev)
{
    if (m_cmd.length()) {
        str stuff = m_cmd + "\n";
        uii.Cmd_Stuff(stuff.c_str());
    }
}

void ExecCmd::setCommand(const char *cmd)
{
    m_cmd = cmd;
}

void ExecCmd::setButton(UIButton *button)
{
    if (m_button) {
        m_button->Disconnect(this, W_Button_Pressed);
    }

    m_button = button;
    if (m_button) {
        m_button->Connect(this, W_Button_Pressed, W_Button_Pressed);
    }
}
