#include <cmath>
#include "Log.hpp"
#include "Renderer.hpp"
#include "Alermath.hpp"

#define WIDTH 640

Renderer::Renderer(sf::RenderWindow* window):
m_window(window),
m_focus(0) {
	m_view.setSize(WIDTH, 360);
	m_view.setCenter(WIDTH * 19.5f, 180);
}

void Renderer::registerDrawable(sf::Drawable* drawable, unsigned z_index, Mode mode) {
	RenderObject ro;
	ro.drawable = drawable;
	ro.z_index = z_index;
	ro.mode = mode;
	m_data.push_back(ro);
}

void Renderer::deregisterDrawable(sf::Drawable* drawable) {
	m_data.erase(std::remove_if(m_data.begin(), m_data.end(), [drawable](auto pair){ 
		return pair.drawable == drawable;
	}), m_data.end());
}

void Renderer::setFocus(int focus) {
	m_focus = focus;
}

int Renderer::getFocus() const {
	return m_focus;
}

int Renderer::getPosition() const {
	return m_focus * WIDTH + WIDTH / 2;
}

void Renderer::sort() {
	std::sort(m_data.begin(), m_data.end(), [](auto o1, auto o2)->bool {
		return o1.mode == o2.mode ? o1.z_index < o2.z_index : o1.mode < o2.mode;
	});
}

void Renderer::clear() {
	m_data.clear();
}

void Renderer::update(float delta) {
	float x1 = m_view.getCenter().x;
	float x2 = getPosition();

	if(x1 != x2) {
		if(std::fabs(x2 - x1) > 2.f) {
			m_view.move(delta * WIDTH * 3.f * math::sgn(x2 - x1), 0.f);
		} else {
			m_view.move(x2 - x1, 0.f);
		}
	}
}

void Renderer::render() {
	bool default_view = true;
	m_window->setView(m_window->getDefaultView());

	for(RenderObject& ro: m_data) {
		if(ro.mode == FG && default_view) {
			default_view = false;
			m_window->setView(m_view);
		}
		if(ro.mode == UI && !default_view) {
			default_view = true;
			m_window->setView(m_window->getDefaultView());
		}
		m_window->draw(*ro.drawable);
	}
	m_window->display();
}