#include <SDL3/SDL.h>
#include <SDL3_image/SDL_image.h>

#include <iostream>
#include <vector>
#include <cstdint>

struct ImageData {
    int width;
    int height;
    std::vector<uint32_t> pixels;
};

// Pretvori SDL_Surface v RGBA8888
ImageData surfaceToImage(SDL_Surface* surface)
{
    ImageData image;
    image.width = surface->w;
    image.height = surface->h;
    image.pixels.resize(image.width * image.height);

    SDL_Surface* converted = SDL_ConvertSurface(
        surface,
        SDL_PIXELFORMAT_RGBA32
    );

    if (!converted) {
        std::cerr << "Napaka pri pretvorbi surface: "
                  << SDL_GetError() << '\n';
        return {};
    }

    const uint8_t* src =
        static_cast<const uint8_t*>(converted->pixels);

    for (int y = 0; y < image.height; ++y) {
        const uint32_t* row =
            reinterpret_cast<const uint32_t*>(
                src + y * converted->pitch
            );

        for (int x = 0; x < image.width; ++x) {
            image.pixels[y * image.width + x] = row[x];
        }
    }

    SDL_DestroySurface(converted);

    return image;
}


// 2. TAB: sivinska slika
ImageData createGrayscale(const ImageData& original)
{
    ImageData gray = original;

    const SDL_PixelFormatDetails* format =
        SDL_GetPixelFormatDetails(SDL_PIXELFORMAT_RGBA32);

    for (size_t i = 0; i < original.pixels.size(); ++i) {

        uint8_t r, g, b, a;

        SDL_GetRGBA(
            original.pixels[i],
            format,
            nullptr,
            &r,
            &g,
            &b,
            &a
        );

        uint8_t value =
            static_cast<uint8_t>(
                0.299 * r +
                0.587 * g +
                0.114 * b
            );

        gray.pixels[i] =
            SDL_MapRGBA(
                format,
                nullptr,
                value,
                value,
                value,
                a
            );
    }

    return gray;
}


// 3. TAB: rotacija za 180°
ImageData rotate180(const ImageData& original)
{
    ImageData rotated = original;

    for (int y = 0; y < original.height; ++y) {
        for (int x = 0; x < original.width; ++x) {

            int sourceIndex =
                y * original.width + x;

            int destX =
                original.width - 1 - x;

            int destY =
                original.height - 1 - y;

            int destIndex =
                destY * original.width + destX;

            rotated.pixels[destIndex] =
                original.pixels[sourceIndex];
        }
    }

    return rotated;
}


// Ustvari SDL texture iz naših podatkov
SDL_Texture* createTexture(
    SDL_Renderer* renderer,
    const ImageData& image
)
{
    SDL_Texture* texture =
        SDL_CreateTexture(
            renderer,
            SDL_PIXELFORMAT_RGBA32,
            SDL_TEXTUREACCESS_STATIC,
            image.width,
            image.height
        );

    if (!texture) {
        std::cerr << "Napaka pri ustvarjanju texture: "
                  << SDL_GetError() << '\n';
        return nullptr;
    }

    SDL_UpdateTexture(
        texture,
        nullptr,
        image.pixels.data(),
        image.width * sizeof(uint32_t)
    );

    return texture;
}


int main(int argc, char* argv[])
{
    if (argc < 2) {
        std::cerr
            << "Uporaba: " << argv[0]
            << " slika.png\n";
        return 1;
    }

    // -------------------------
    // SDL inicializacija
    // -------------------------

    if (!SDL_Init(SDL_INIT_VIDEO)) {
        std::cerr
            << "SDL_Init napaka: "
            << SDL_GetError() << '\n';
        return 1;
    }

    if (!SDL_Init(SDL_INIT_VIDEO)) {
        std::cerr
            << "SDL_Init napaka: "
            << SDL_GetError() << '\n';
        return 1;
    }


    // -------------------------
    // Naloži PNG
    // -------------------------

    SDL_Surface* surface =
        IMG_Load(argv[1]);

    if (!surface) {
        std::cerr
            << "Napaka pri nalaganju slike: "
            << SDL_GetError() << '\n';

        SDL_Quit();
        return 1;
    }


    ImageData original =
        surfaceToImage(surface);

    SDL_DestroySurface(surface);


    if (original.pixels.empty()) {
        SDL_Quit();
        return 1;
    }


    // -------------------------
    // Ustvari različice
    // -------------------------

    ImageData grayscale =
        createGrayscale(original);

    ImageData rotated =
        rotate180(original);


    // -------------------------
    // Okno
    // -------------------------

    SDL_Window* window =
        SDL_CreateWindow(
            "SDL3 Image Viewer",
            1000,
            800,
            SDL_WINDOW_RESIZABLE
        );

    if (!window) {
        std::cerr
            << "Napaka pri oknu: "
            << SDL_GetError() << '\n';

        SDL_Quit();
        return 1;
    }


    SDL_Renderer* renderer =
        SDL_CreateRenderer(window, nullptr);

    if (!renderer) {
        std::cerr
            << "Napaka pri rendererju: "
            << SDL_GetError() << '\n';

        SDL_DestroyWindow(window);
        SDL_Quit();
        return 1;
    }


    // -------------------------
    // Texture
    // -------------------------

    SDL_Texture* textures[3];

    textures[0] =
        createTexture(renderer, original);

    textures[1] =
        createTexture(renderer, grayscale);

    textures[2] =
        createTexture(renderer, rotated);


    // -------------------------
    // Glavna zanka
    // -------------------------

    bool running = true;

    int activeTab = 0;

    SDL_Event event;

    while (running) {

        while (SDL_PollEvent(&event)) {

            if (event.type == SDL_EVENT_QUIT) {
                running = false;
            }

            // Klik na enega od tabov
            if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN &&
                event.button.button == SDL_BUTTON_LEFT) {

                float mouseX = event.button.x;
                float mouseY = event.button.y;

                if (mouseY >= 0 && mouseY < 50) {

                    int tabWidth = 1000 / 3;

                    int clickedTab =
                        static_cast<int>(
                            mouseX / tabWidth
                        );

                    if (clickedTab >= 0 &&
                        clickedTab < 3) {

                        activeTab = clickedTab;
                    }
                }
            }

            // Tipke 1, 2 in 3
            if (event.type == SDL_EVENT_KEY_DOWN) {

                if (event.key.key == SDLK_1)
                    activeTab = 0;

                if (event.key.key == SDLK_2)
                    activeTab = 1;

                if (event.key.key == SDLK_3)
                    activeTab = 2;

                if (event.key.key == SDLK_ESCAPE)
                    running = false;
            }
        }


        // -------------------------
        // Risanje
        // -------------------------

        int windowWidth;
        int windowHeight;

        SDL_GetWindowSize(
            window,
            &windowWidth,
            &windowHeight
        );


        // Ozadje
        SDL_SetRenderDrawColor(
            renderer,
            30, 30, 30, 255
        );

        SDL_RenderClear(renderer);


        // -------------------------
        // Tabi
        // -------------------------

        int tabHeight = 50;
        int tabWidth = windowWidth / 3;

        const char* tabNames[3] = {
            "Original",
            "Sivinska",
            "180 stopinj"
        };


        for (int i = 0; i < 3; ++i) {

            SDL_FRect tabRect{
                static_cast<float>(i * tabWidth),
                0,
                static_cast<float>(tabWidth),
                static_cast<float>(tabHeight)
            };


            if (i == activeTab) {
                SDL_SetRenderDrawColor(
                    renderer,
                    70, 120, 200, 255
                );
            }
            else {
                SDL_SetRenderDrawColor(
                    renderer,
                    60, 60, 60, 255
                );
            }

            SDL_RenderFillRect(
                renderer,
                &tabRect
            );
        }


        // -------------------------
        // Trenutna slika
        // -------------------------

        ImageData* current =
            nullptr;

        if (activeTab == 0)
            current = &original;

        else if (activeTab == 1)
            current = &grayscale;

        else
            current = &rotated;


        float availableWidth =
            static_cast<float>(windowWidth);

        float availableHeight =
            static_cast<float>(
                windowHeight - tabHeight
            );


        // Ohrani razmerje slike
        float scaleX =
            availableWidth / current->width;

        float scaleY =
            availableHeight / current->height;

        float scale =
            std::min(scaleX, scaleY);


        float imageWidth =
            current->width * scale;

        float imageHeight =
            current->height * scale;


        SDL_FRect destination{
            (availableWidth - imageWidth) / 2.0f,
            tabHeight +
                (availableHeight - imageHeight) / 2.0f,
            imageWidth,
            imageHeight
        };


        SDL_RenderTexture(
            renderer,
            textures[activeTab],
            nullptr,
            &destination
        );


        SDL_RenderPresent(renderer);
    }


    // -------------------------
    // Čiščenje
    // -------------------------

    for (SDL_Texture* texture : textures) {
        SDL_DestroyTexture(texture);
    }

    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);

    SDL_Quit();

    return 0;
}