//
// Created by sasha on 27.11.2025.
//

#include "iwidget.h"

#include <algorithm>

#include "engine/engine.h"

IWidget::IWidget(IWidget *parent, float x, float y, float width, float height) {
    this->parent=parent;

    this->x = x;
    this->y = y;
    this->width = width;
    this->height = height;

    this->visible = true;
    this->stateClick = 0;

    this->name = "";

    if (parent) {
        parent->addWidget(this);
    }
}

IWidget::~IWidget() {
    auto tmplistWidgets = listWidgets;
    for (IWidget* widget : tmplistWidgets){
        delete widget;
    }
    listWidgets.clear();

    if (parent) {
        parent->removeWidget(this);
    }
}



SDL_FRect IWidget::getScaleFRect() {
    float deltaX = (Engine::getWindowSize().w - Engine::getTemplateWindowSize().w*Engine::scale())/2;
    return SDL_FRect {deltaX+x*Engine::scale(),y*Engine::scale(),width*Engine::scale(),height*Engine::scale()};
}

void IWidget::setSize(float width, float height) {
    this->width = width;
    this->height = height;
}

void IWidget::move(float x, float y) {
    this->x = x;
    this->y = y;
}

SDL_FRect IWidget::getFRect() {
    return SDL_FRect{x,y,width,height};
}

void IWidget::show() {
    visible = true;
}

void IWidget::hide() {
    visible = false;
}

bool IWidget::isVisible() {
    return visible;
}

void IWidget::setName(const std::string &name) {
    this->name=name;
}

void IWidget::addWidget(IWidget *widget) {
    listWidgets.push_back(widget);
}

void IWidget::removeWidget(IWidget *widget) {
    listWidgets.erase(std::remove(listWidgets.begin(), listWidgets.end(), widget), listWidgets.end());
}



// virtual
void IWidget::event(const SDL_Event &event) {
    if (!isVisible()) return;

    SDL_FRect rect_windows = Engine::getWindowSize();

    switch (event.type) {
        case SDL_EVENT_QUIT: {
            //return false;
            break;
        }
        case SDL_EVENT_WINDOW_RESIZED: {
            //onWindowResize();
            break;
        }

        case SDL_EVENT_MOUSE_BUTTON_DOWN:
        case SDL_EVENT_FINGER_DOWN: {
            float logicalX = event.tfinger.x * rect_windows.w;
            float logicalY = event.tfinger.y * rect_windows.h;
            if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN){
                logicalX = event.button.x;
                logicalY = event.button.y;
            }

            SDL_FRect scaleRect = getScaleFRect();

            if (logicalX>=scaleRect.x and logicalX<=scaleRect.x+scaleRect.w and
                logicalY>=scaleRect.y and logicalY<=scaleRect.y+scaleRect.h)
            {
                SDL_Log("[%s] SDL_EVENT_FINGER_DOWN",name.c_str());
                if (callbacks.count(CallbackType::EVENT_FINGER_DOWN)){
                    callbacks[CallbackType::EVENT_FINGER_DOWN]();
                }
                stateClick = SDL_EVENT_MOUSE_BUTTON_DOWN;
            }
            break;
        }

        case SDL_EVENT_MOUSE_BUTTON_UP:
        case SDL_EVENT_FINGER_UP: {
            float logicalX = event.tfinger.x * (float)rect_windows.w;
            float logicalY = event.tfinger.y * (float)rect_windows.h;
            if (event.type == SDL_EVENT_MOUSE_BUTTON_UP){
                logicalX = event.button.x;
                logicalY = event.button.y;
            }

            SDL_FRect scaleRect = getScaleFRect();

            if (logicalX>=scaleRect.x and logicalX<=scaleRect.x+scaleRect.w and
                logicalY>=scaleRect.y and logicalY<=scaleRect.y+scaleRect.h)
            {
                SDL_Log("[%s] SDL_EVENT_FINGER_UP",name.c_str());
                if (callbacks.count(CallbackType::EVENT_FINGER_UP)){
                    callbacks[CallbackType::EVENT_FINGER_UP]();
                }

                // onClick
                if (stateClick==SDL_EVENT_MOUSE_BUTTON_DOWN){
                    SDL_Log("[%s] EVENT_ON_CLICK",name.c_str());
                    if (callbacks.count(CallbackType::EVENT_ON_CLICK)){
                        callbacks[CallbackType::EVENT_ON_CLICK]();
                    }
                }
            }

            stateClick=0;
            break;
        }
    }

}

void IWidget::setCallback(CallbackType type, std::function<void()> func) {
    callbacks[type] = func;
}

void IWidget::draw() {}
void IWidget::iterate() {}

void IWidget::drawAll() {
    if (!isVisible()) return;

    this->draw();

    for (auto widget : listWidgets) {
        if (widget) {
            widget->drawAll();
        }
    }
}

void IWidget::eventAll(const SDL_Event &event) {
    if (!isVisible()) return;

    this->event(event);

    for (auto widget : listWidgets) {
        if (widget) {
            widget->eventAll(event);
        }
    }
}

void IWidget::iterateAll() {
    this->iterate();

    for (auto widget : listWidgets) {
        if (widget) {
            widget->iterateAll();
        }
    }
}




