﻿using System;
using OpenTK.Graphics.OpenGL;

namespace Adventure.Framework.Content
{
    public sealed class Shader : IDisposable
    {
        private int programID;

        public Shader()
        {
            programID = GL.CreateProgram();
        }

        public void LoadSource(ShaderType type, string @source)
        {
            int shaderID = GL.CreateShader(type);
            GL.ShaderSource(shaderID, source);
            GL.CompileShader(shaderID);

            checkCompilationStatus(shaderID, type);

            GL.AttachShader(programID, shaderID);
            GL.DeleteShader(shaderID);
        }
        public void LinkShader()
        {
            GL.LinkProgram(programID);
        }
        public void Use()
        {
            GL.UseProgram(programID);
        }

        public void Dispose()
        {
            GL.DeleteProgram(programID);
        }

        private void checkCompilationStatus(int id, ShaderType type)
        {
            int compileStatus;
            GL.GetShader(id, ShaderParameter.CompileStatus, out compileStatus);

            if (compileStatus == COMPILE_ERROR)
            {
                string errorMsg = String.Format("Shader Compile Error.  ID {0} ({1}).  Error message: {2}", id, type.ToString(), GL.GetShaderInfoLog(id));

                throw new ShaderCompilationErrorException(errorMsg);
            }
        }

        private const int COMPILE_ERROR = 0;

        public int ID { get { return programID; } }
    }

    public class ShaderCompilationErrorException : Exception
    {
        public ShaderCompilationErrorException() : base() { }
        public ShaderCompilationErrorException(string msg) : base(msg) { }
        public ShaderCompilationErrorException(string msg, Exception inner) : base(msg, inner) { }
    }
}
