#include "vkvm.hpp"
#include <cmath>
#include <random>
#include <chrono>
#include <unistd.h>
#include <internal.hpp>
#include <thread>

void sinus() {
    for (int x = 0; x < vkvm::getWidth(); ++x) {
        double y = 300 * sin(x);
        vkvm::log(vkvm::LogLevel::DEBUG, y);
        vkvm::setPixel(x, static_cast<int>(y), vkvm::getForegroundColor());
    }
}

long double map(long double value, long double inputMin, long double inputMax, long double outputMin, long double outputMax) {
    return (value - inputMin) * (outputMax - outputMin) / (inputMax - inputMin) + outputMin;
}

void mandelbrot() {
    vkvm::setWidth(600);
    vkvm::setHeight(800);

    int width = vkvm::getWidth();
    int height = vkvm::getHeight();

    long double min = -2.84;
    long double max = 1;
    int maxIterations = 200;
    double factor = 1;

    for (int count = 0; count < 10000; count++) {
        max -= 0.1 * factor;
        min += 0.15 * factor;
        factor *= 0.9349;
        maxIterations += 5;

        if(count > 30) {
            maxIterations *= 1.02;
        }

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

                long double xMap = map(x, 0, width, min, max);
                long double yMap = map(y, 0, height, min, max);

                long double xInitial = xMap;
                long double yInitial = yMap;

                int n = 0;

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

                    long double x1 = xMap * xMap - yMap * yMap;
                    long double y1 = 2 * xMap * yMap;

                    xMap = x1 + xInitial;
                    yMap = y1 + yInitial;

                    if ((xMap + yMap) > 2) {
                        break;
                    }


                    n++;
                }

                int brightness = map(n, 0, maxIterations, 0, 255);
                if (n == maxIterations || (brightness < 20)) {
                    brightness = 0;
                }

                int red = map(brightness * brightness, 0, 255 * 255, 0, 255);
                int green = brightness;
                int blue = map(sqrt(brightness), 0, sqrt(255), 0, 255);


                vkvm::setPixel(x, y, vkvm::Color(red, green, blue));

            }
        }
        vkvm::callEvent(vkvm::EventType::Redraw);
    }
}
