﻿using Nemesis.Rendering;
using Nemesis.Rendering.OpenGL.Shader;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;

namespace NemesisGame.Rendering.OpenGL
{
    public sealed class MatrixProgram : MeshProgram
    {
        private readonly int uniform_M = 0;
        private readonly int uniform_V = 0;
        private readonly int uniform_P = 0;

        private readonly int[] uniform_textures = new int[3];

        private readonly int uniform_alphaBlend = 0;

        public MatrixProgram()
            : base(
                new MeshProgramVertexAttributes("vertexPosition_modelspace", string.Empty, "vertexUV"),
                ShaderSource.FromSourceFile("Rendering/OpenGL/Shader/GLSL/MatrixProgram_vs.glsl"),
                ShaderSource.FromSourceFile("Rendering/OpenGL/Shader/GLSL/MatrixProgram_fs.glsl")
            )
        {
            uniform_M = GetUniformLocation("M");
            uniform_V = GetUniformLocation("V");
            uniform_P = GetUniformLocation("P");

            uniform_textures[0] = GetUniformLocation("textureGameScene");
            uniform_textures[1] = GetUniformLocation("textureFont");
            uniform_textures[2] = GetUniformLocation("textureCharacterMask");

            uniform_alphaBlend = GetUniformLocation("alphaBlend");
        }

        public sealed override void EnableTexture(ITexture texture, int textureUnit)
        {
            GL.Uniform1(uniform_textures[textureUnit], textureUnit);

            GL.ActiveTexture(TextureUnit.Texture0 + textureUnit);
            texture.Bind();
        }

        public sealed override void DisableTexture()
        {
            // nothing to do
        }

        public sealed override void SetMaterialColor(Color4 diffuse, Color4 specular, Color4 ambient)
        {
            // nothing to do
        }

        public sealed override void SetModelMatrix(Matrix4 modelMatrix)
        {
            GL.UniformMatrix4(uniform_M, false, ref modelMatrix);
        }

        public sealed override void SetViewMatrix(Matrix4 viewMatrix)
        {
            GL.UniformMatrix4(uniform_V, false, ref viewMatrix);
        }

        public sealed override void SetProjectionMatrix(Matrix4 projectionMatrix)
        {
            GL.UniformMatrix4(uniform_P, false, ref projectionMatrix);
        }

        public void SetAlphaBlend(float blend)
        {
            GL.Uniform1(uniform_alphaBlend, blend);
        }
    }
}
