#include "render/shaders/EntityShader.h"

namespace td {
namespace shader {

#ifdef __ANDROID__
static const char vertexSource[] =
R"(#version 300 es

precision mediump float;

layout(location = 0) in vec2 position;
layout(location = 1) in int color;

uniform vec2 camPos;
uniform float zoom;
uniform float aspectRatio;
uniform vec2 translation;
uniform float isometricView;

flat out int pass_color;

void main(void){
    float modelX = position.x + translation.x;
    float modelY = position.y + translation.y;
    float x = (modelX - camPos.x - (modelY - camPos.y) * isometricView) / aspectRatio * zoom;
    float y = ((0.5 * (modelX - camPos.x) + 0.5 * (modelY - camPos.y)) * isometricView + (modelY - camPos.y) * (1.0 - isometricView)) * zoom;
	pass_color = color;
	gl_Position = vec4(x, -y, 0.0, 1.0);
}
)";

static const char fragmentSource[] =
R"(#version 300 es

precision mediump float;

flat in int pass_color;

out vec4 out_color;

void main(void){

    float r = float(pass_color >> 24 & 0xFF) / 255.0;
    float g = float(pass_color >> 16 & 0xFF) / 255.0;
    float b = float(pass_color >> 8 & 0xFF) / 255.0;
    float a = float(pass_color & 0xFF) / 255.0; 
	out_color = vec4(r, g, b, a);

}
)";
#else
static const char vertexSource[] = R"(
#version 330

layout(location = 0) in vec2 position;
layout(location = 1) in int color;

uniform vec2 camPos;
uniform float zoom;
uniform float aspectRatio;
uniform vec2 translation;
uniform float isometricView;

flat out int pass_color;

void main(void){
    float modelX = position.x + translation.x;
    float modelY = position.y + translation.y;
    float x = (modelX - camPos.x - (modelY - camPos.y) * isometricView) / aspectRatio * zoom;
    float y = ((0.5 * (modelX - camPos.x) + 0.5 * (modelY - camPos.y)) * isometricView + (modelY - camPos.y) * (1.0 - isometricView)) * zoom;
	pass_color = color;
	gl_Position = vec4(x, -y, 0.0, 1.0);
}
)";

static const char fragmentSource[] = R"(
#version 330

flat in int pass_color;

out vec4 out_color;

void main(void){

    float r = float(pass_color >> 24 & 0xFF) / 255.0;
    float g = float(pass_color >> 16 & 0xFF) / 255.0;
    float b = float(pass_color >> 8 & 0xFF) / 255.0;
    float a = float(pass_color & 0xFF) / 255.0; 
	out_color = vec4(r, g, b, a);

}
)";
#endif

EntityShader::EntityShader() : ShaderProgram() {}

void EntityShader::LoadShader() {
    ShaderProgram::LoadProgram(vertexSource, fragmentSource);
}

void EntityShader::GetAllUniformLocation() {
    m_LocationAspectRatio = static_cast<unsigned int>(GetUniformLocation("aspectRatio"));
    m_LocationZoom = static_cast<unsigned int>(GetUniformLocation("zoom"));
    m_LocationCam = static_cast<unsigned int>(GetUniformLocation("camPos"));
    m_LocationTranslation = static_cast<unsigned int>(GetUniformLocation("translation"));
    m_LocationViewtype = static_cast<unsigned int>(GetUniformLocation("isometricView"));
}

void EntityShader::SetCamPos(const glm::vec2& camPos) {
    LoadVector(m_LocationCam, camPos);
}
void EntityShader::SetZoom(float zoom) {
    LoadFloat(m_LocationZoom, zoom);
}
void EntityShader::SetAspectRatio(float aspectRatio) {
    LoadFloat(m_LocationAspectRatio, aspectRatio);
}
void EntityShader::SetModelPos(const glm::vec2& modelPos) {
    LoadVector(m_LocationTranslation, modelPos);
}
void EntityShader::SetIsometricView(float isometric) {
    LoadFloat(m_LocationViewtype, isometric);
}


} // namespace shader
} // namespace td