#include "game/momia.hpp"

#include <cstdlib>

#include "core/jail/jgame.hpp"

Momia::Momia(Jd8::Surface gfx, bool dimoni, Uint16 x, Uint16 y, Prota* sam)
    : Sprite(gfx) {
    this->dimoni = dimoni;
    this->sam_ = sam;

    entitat.frames.reserve(20);
    for (int row = 0; row < 4; row++) {
        for (int col = 0; col < 5; col++) {
            Frame f;
            f.w = 15;
            f.h = 15;
            if (Info::ctx.num_piramide == 4) {
                f.h -= 5;
            }
            f.x = (col * 15) + 75;
            if (this->dimoni) {
                f.x += 75;
            }
            f.y = 20 + (row * 15);
            entitat.frames.push_back(f);
        }
    }

    entitat.animacions.resize(4);
    for (int i = 0; i < 4; i++) {
        entitat.animacions[i].frames = {
            static_cast<Uint8>(0 + (i * 5)),
            static_cast<Uint8>(1 + (i * 5)),
            static_cast<Uint8>(2 + (i * 5)),
            static_cast<Uint8>(1 + (i * 5)),
            static_cast<Uint8>(0 + (i * 5)),
            static_cast<Uint8>(3 + (i * 5)),
            static_cast<Uint8>(4 + (i * 5)),
            static_cast<Uint8>(3 + (i * 5)),
        };
    }

    this->cur_frame = 0;
    this->o = rand() % 4;
    this->cycles_per_frame_ = 4;

    if (this->dimoni) {
        if (x == 0) {
            this->x = 150;
        } else {
            this->x = x;
        }
        if (y == 0) {
            if (this->sam_->y > 100) {
                this->y = 30;
            } else {
                this->y = 170;
            }
        } else {
            this->y = y;
        }
        this->engendro_ = std::make_unique<Engendro>(gfx, this->x, this->y);
    } else {
        this->x = x;
        this->y = y;
    }
}

void Momia::draw() {
    if (this->engendro_) {
        this->engendro_->draw();
    } else {
        Sprite::draw();

        if (Info::ctx.num_piramide == 4) {
            if ((Jg::getCycleCounter() % 40) < 20) {
                Jd8::blitCK(this->x, this->y, this->gfx_, 220, 80, 15, 15, 255);
            } else {
                Jd8::blitCK(this->x, this->y, this->gfx_, 235, 80, 15, 15, 255);
            }
        }
    }
}

void Momia::pickHorizontalThenVertical() {
    if (this->x > this->sam_->x) {
        this->o = 3;
    } else if (this->x < this->sam_->x) {
        this->o = 2;
    } else if (this->y < this->sam_->y) {
        this->o = 0;
    } else if (this->y > this->sam_->y) {
        this->o = 1;
    }
}

void Momia::pickVerticalThenHorizontal() {
    if (this->y < this->sam_->y) {
        this->o = 0;
    } else if (this->y > this->sam_->y) {
        this->o = 1;
    } else if (this->x > this->sam_->x) {
        this->o = 3;
    } else if (this->x < this->sam_->x) {
        this->o = 2;
    }
}

void Momia::pickDirection() {
    if (!this->dimoni) {
        this->o = rand() % 4;
        return;
    }
    if (rand() % 2 == 0) {
        pickHorizontalThenVertical();
    } else {
        pickVerticalThenHorizontal();
    }
}

void Momia::stepInDirection() {
    switch (this->o) {
        case 0:
            if (y < 170) { this->y++; }
            break;
        case 1:
            if (y > 30) { this->y--; }
            break;
        case 2:
            if (x < 280) { this->x++; }
            break;
        case 3:
            if (x > 20) { this->x--; }
            break;
        default:
            break;
    }
}

auto Momia::collidesWithSam() const -> bool {
    return this->x > (this->sam_->x - 7) && this->x < (this->sam_->x + 7) &&
        this->y > (this->sam_->y - 7) && this->y < (this->sam_->y + 7);
}

void Momia::applyCollisionWithSam() {
    if (this->sam_->pergami) {
        this->sam_->pergami = false;
        return;
    }
    Info::ctx.vida--;
    if (Info::ctx.vida == 0) {
        this->sam_->o = 5;
    }
}

auto Momia::update() -> bool {
    if (this->engendro_) {
        if (this->engendro_->update()) {
            this->engendro_.reset();
        }
        return false;
    }
    const bool SAM_ALIVE = this->sam_->o < 4;
    const bool MAY_STEP = this->dimoni || Info::ctx.num_piramide == 5 || Jg::getCycleCounter() % 2 == 0;
    if (!SAM_ALIVE || !MAY_STEP) {
        return false;
    }
    if ((this->x - 20) % 65 == 0 && (this->y - 30) % 35 == 0) {
        pickDirection();
    }
    stepInDirection();
    if (Jg::getCycleCounter() % this->cycles_per_frame_ == 0) {
        this->cur_frame++;
        if (this->cur_frame == entitat.animacions[this->o].frames.size()) {
            this->cur_frame = 0;
        }
    }
    if (collidesWithSam()) {
        applyCollisionWithSam();
        return true;
    }
    return false;
}
