/*
	OmniaFramework - A collection of useful functionality
	Copyright (C) 2026  OmniaX-Dev

	This file is part of OmniaFramework.

	OmniaFramework 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 3 of the License, or
	(at your option) any later version.

	OmniaFramework 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 OmniaFramework.  If not, see <https://www.gnu.org/licenses/>.
*/

#include "Animation.hpp"
#include "../../ostd/math/Random.hpp"

namespace ogfx
{
	Animation& Animation::create(const AnimationData& ad, Image& spriteSheet)
	{
		m_animData = ad;
		m_spriteSheet = &spriteSheet;
		m_timer.startCount(ostd::eTimeUnits::Milliseconds);
		update_animation();
		return *this;
	}

	void Animation::update(void)
	{
		f64 dtms = (1.0 / cast<f64>(m_animData.fps)) * 1000.0;
		if (m_timer.read() >= dtms)
		{
			update_animation();
			m_timer.restart(ostd::eTimeUnits::Milliseconds);
		}
	}

	void Animation::resetAnimation(void)
	{
		m_currentFrame = 0;
	}

	void Animation::update_animation(void)
	{
		if (!m_animData.still)
		{
			if (m_animData.random)
			{
				m_currentFrame = ostd::Random::geti32(0, m_animData.frameCount);
			}
			else if (m_animData.turnBack)
			{
				if (!m_back && m_currentFrame >= m_animData.frameCount - 1)
				{
					m_back = true;
					m_currentFrame--;
				}
				else if (!m_back)
					m_currentFrame++;
				else if (m_back && m_currentFrame <= 0)
				{
					m_back = false;
					m_currentFrame++;
				}
				else if (m_back)
					m_currentFrame--;
			}
			else
			{
				if (m_currentFrame++ >= m_animData.frameCount - 1)
					m_currentFrame = 0;
			}
		}
		else if (m_animData.still)
		{
			if (m_animData.stillFrame >= 0 && m_animData.stillFrame < m_animData.frameCount)
				m_currentFrame = m_animData.stillFrame;
			else
				m_currentFrame = 0;
		}
		if (m_animData.columns <= 0) return;
		i32 col = m_currentFrame % m_animData.columns;
		i32 row = (m_animData.rows > 1) ? cast<i32>(m_currentFrame / m_animData.columns) : 0;

		i32 x = m_animData.pixelOffsetX
			  + ((col + m_animData.columnOffset) * (m_animData.frameWidth + m_animData.spacingX));

		i32 y = m_animData.pixelOffsetY
			  + ((row + m_animData.rowOffset) * (m_animData.frameHeight + m_animData.spacingY));

		m_frameRect = { cast<f32>(x), cast<f32>(y), m_animData.frameWidth, m_animData.frameHeight };
	}
}
