using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using System.Text;
using System.Threading.Tasks;
using OpenTK;
using OpenTK.Input;
using OpenTK.Graphics.OpenGL;
using OpenTK.Graphics;
using bbiwarg.Input.InputHandling;
using bbiwarg.Input.InputProviding;
using bbiwarg.Utility;

namespace bbiwarg.Output.GlassesOutput
{
    class GlassesWindow : GameWindow
    {
        private InputHandler inputHandler;
        private InputProvider inputProvider;
        private uint textureID;
        private int currentFrameID;
        private OutputImage image;

        public GlassesWindow(InputProvider inputProvider, InputHandler inputHandler)
            : base(Parameters.GlassesWindowWidth, Parameters.GlassesWindowHeight)
        {
            this.inputProvider = inputProvider;
            this.inputHandler = inputHandler;
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            Title = Parameters.GlassesWindowTitle;
            GL.ClearColor(Color.Black);
            /*
            // transparency
            GL.Enable(EnableCap.Blend);
            GL.BlendEquation(BlendEquationMode.Max);

            // Depth Test 
            GL.Enable(EnableCap.DepthTest);
            */
            // Texture
            GL.Enable(EnableCap.Texture2D);
            GL.GenTextures(1, out textureID);
            GL.BindTexture(TextureTarget.Texture2D, textureID);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);

            Keyboard.KeyDown += handleKeyDown;
        }

        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            base.OnClosing(e);

            inputProvider.stop();
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);

            int screenWidth = ClientRectangle.Width;
            int screenHeight = ClientRectangle.Height;
            /*
            int numRows = 1 + (Parameters.DebugWindowNumImages - 1) / Parameters.DebugWindowNumImagesPerRow;
            int numCols = Math.Min(Parameters.DebugWindowNumImages, Parameters.DebugWindowNumImagesPerRow);
            int heightForWidth = (int)((float)screenWidth / ((float)numCols * Parameters.ImageAspectRatio) * (float)numRows);
            */
            GL.Viewport(0, 0, screenWidth, screenHeight);
            //GL.Viewport(0, (screenHeight - heightForWidth) / 2, screenWidth, heightForWidth);

            //Matrix4 projection = Matrix4.CreateOrthographicOffCenter(0, numCols, numRows, 0, 0.001f, 10f);
            Matrix4 projection = Matrix4.CreateOrthographicOffCenter(0, 1, 1, 0, 0.001f, 10f);
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadMatrix(ref projection);
        }

        protected override void OnUpdateFrame(FrameEventArgs e)
        {
            Timer.start("GlassesWindow.OnUpdateFrame");
            base.OnUpdateFrame(e);

            if (!inputProvider.IsActive)
                Exit();

            FrameData frameData = inputHandler.FrameData;
            if (frameData != null)
            {
                lock (frameData)
                {
                    if (currentFrameID != frameData.FrameID)
                    {
                        currentFrameID = frameData.FrameID;

                        Timer.start("GlassesWindow.OnUpdateFrame::updateImage");
                        //TODO update image
                        image = new OutputImage(Parameters.GlassesWindowWidth, Parameters.GlassesWindowHeight);
                        Timer.stop("GlassesWindow.OnUpdateFrame::updateImage");
                    }
                }
            }

            Timer.stop("GlassesWindow.OnUpdateFrame");
        }


        protected override void OnRenderFrame(FrameEventArgs e)
        {
            Timer.start("GlassesWindow.OnRenderFrame");
            base.OnRenderFrame(e);
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
            Matrix4 modelview = Matrix4.LookAt(Vector3.Zero, -Vector3.UnitZ, Vector3.UnitY);
            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadMatrix(ref modelview);

            Title = Parameters.DebugWindowTitle + " (Frame: " + currentFrameID + ")";

            GL.Enable(EnableCap.Texture2D);

            Timer.start("GlassesWindow.OnRenderFrame::drawImage");
            
            GL.BindTexture(TextureTarget.Texture2D, textureID);
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, Parameters.ImageWidth, Parameters.ImageHeight, 0, PixelFormat.Rgb, PixelType.UnsignedByte, image.Image.MIplImage.imageData);
            GL.Begin(PrimitiveType.Quads);
            GL.Color3(1.0, 1.0, 1.0);
            GL.TexCoord2(0, 0); GL.Vertex3(0, 0, -1);
            GL.TexCoord2(1, 0); GL.Vertex3(1, 0, -1);
            GL.TexCoord2(1, 1); GL.Vertex3(1, 1, -1);
            GL.TexCoord2(0, 1); GL.Vertex3(0, 1, -1);
            GL.End();

            Timer.stop("GlassesWindow.OnRenderFrame::drawImage");

            Timer.start("GlassesWindow.OnRenderFrame::SwapBuffers");
            SwapBuffers();
            Timer.stop("GlassesWindow.OnRenderFrame::SwapBuffers");

            Timer.stop("GlassesWindow.OnRenderFrame");
        }

        private void handleKeyDown(object sender, KeyboardKeyEventArgs e)
        {
            Console.WriteLine("jens ist plööhöhöhöhööt");
        }

    }
}
