using System;
using System.Collections.Generic;
using System.Threading;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using EZGL2D;

namespace EZGL2DexampleSprites
{
    public class GL2Dexample : GameWindow    // inherit the GameWindow class
    {
        const int SCREEN_WIDTH = 640;        // screen dimensions
        const int SCREEN_HEIGHT = 480;

        GL2D.SpriteGL plantSprite;          // our single plant texture
        GL2D.SpriteGL magicSprite;          // our magic texture
        GL2D.SpriteGL[] atlasSprites;       // sprites loaded via image atlas
        GL2D.SpriteGL[] femaleSprites;      // sprites loaded without image atlas

        float angle = 0;        // angle of rotation of our magic sprite
        float px = 320;         // location of the movable plant sprite(use th keyboard)
        float py = 80;
        float speed = 5;        // speed of movement
        int frame = 0;          // standard frame counter
        int megaFrame = 0;      // frame to animate the "megaman" 
        int chickFrame = 0;      // frame to animate the "female" 
        
        public GL2Dexample()
            : base(SCREEN_WIDTH, SCREEN_HEIGHT)
        {
        }

        // this is where you would initialize everything
        // like loading textures, setting up OpenGL screen, etc.
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            VSync = VSyncMode.On;                           // force vertical synching
            Title = "EZ Sprites!";  // set the title
            //WindowBorder = WindowBorder.Hidden;             // hide the window

            GL2D.Screen2D(Width, Height);     // init our OpenGL screen

            plantSprite = GL2D.LoadSprite("data/EZGL2DexampleSprites/plant.png", (int)TextureMinFilter.Linear);    // load the texture
            magicSprite = GL2D.LoadSprite("data/EZGL2DexampleSprites/magic.png", (int)TextureMinFilter.Linear);    // load the texture
            atlasSprites = GL2D.LoadSpriteSet("data/EZGL2DexampleSprites/atlas.png",                               // load texture via sprite atlas
                                              Atlas.atlasCoords.Length / 4,
                                              Atlas.atlasCoords,
                                              (int)TextureMinFilter.Linear);
            femaleSprites = GL2D.LoadTileSet("data/EZGL2DexampleSprites/female.png",
                                              32, 32, (int)TextureMinFilter.Nearest);   // Nearest for oldskool effect
 
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            GL2D.Screen2D(Width, Height);       // reset the screen every resize
        }

        // this is where all your game logic
        // should be done. (Input, Entity movement, collisions, etc)
        protected override void OnUpdateFrame(FrameEventArgs e)
        {
            base.OnUpdateFrame(e);

            frame++;
            angle += 5;     // increment angle

            // Animate sprites(female and megaman) every 8th frame
            if ((frame & 7) == 0)
            {
                megaFrame++;
                if (megaFrame > 7) megaFrame = 0;
                chickFrame++;
                if (chickFrame > 2) chickFrame = 0;
            }

            // get input
            if (Keyboard[OpenTK.Input.Key.Up]) py -= speed;
            if (Keyboard[OpenTK.Input.Key.Down]) py += speed;
            if (Keyboard[OpenTK.Input.Key.Left]) px -= speed;
            if (Keyboard[OpenTK.Input.Key.Right]) px += speed;

            if (Keyboard[OpenTK.Input.Key.Escape])
            {
                this.Exit();
                return;
            }
        }

        protected override void OnRenderFrame(FrameEventArgs e)
        {
            base.OnRenderFrame(e);

            GL2D.ClearScreen();   // clear the screen

            GL2D.Begin2D();         // start 2D drawing mode

                
                // Draw a line of plants flipped
                GL2D.SetColor(1, 1, 1, 1);
                GL2D.BlendMode(GL2D.BLEND_MODE.GL2D_ALPHA);
                GL2D.Sprite(170 * 0, 0, GL2D.SpriteGL.FLIP_NONE, plantSprite);
                GL2D.Sprite(170 * 1, 0, GL2D.SpriteGL.FLIP_H, plantSprite);
                GL2D.Sprite(170 * 2, 0, GL2D.SpriteGL.FLIP_V, plantSprite);
                GL2D.Sprite(170 * 3, 0, GL2D.SpriteGL.FLIP_H | GL2D.SpriteGL.FLIP_V, plantSprite);

                // Draw a line of plants flipped
                // but with different colors
                GL2D.BlendMode(GL2D.BLEND_MODE.GL2D_ALPHA);
                GL2D.SetColor(1, 0, 0, 1);
                GL2D.Sprite(170 * 0, 340, GL2D.SpriteGL.FLIP_NONE, plantSprite);
                GL2D.SetColor(0, 1, 0, 1);
                GL2D.Sprite(170 * 1, 340, GL2D.SpriteGL.FLIP_H, plantSprite);
                GL2D.SetColor(0, 0, 1, 1);
                GL2D.Sprite(170 * 2, 340, GL2D.SpriteGL.FLIP_V, plantSprite);
                GL2D.SetColor(0, 1, 1, 1);
                GL2D.Sprite(170 * 3, 340, GL2D.SpriteGL.FLIP_H | GL2D.SpriteGL.FLIP_V, plantSprite);

                // show rotation and scaling
                GL2D.SetColor(1, 1, 1, 1);
                GL2D.BlendMode(GL2D.BLEND_MODE.GL2D_ALPHA);
                float scaleX = (float)Math.Sin(frame / 20.0) * 2;
                float scaleY = (float)Math.Sin(frame / 25.0) * 2;
                GL2D.SpriteRotateScale(100, 240, angle, scaleX, scaleY, GL2D.SpriteGL.FLIP_NONE, magicSprite);
                GL2D.SpriteRotateScale(540, 240, -angle, -scaleX, -scaleY, GL2D.SpriteGL.FLIP_NONE, magicSprite);

                // Glow lines!
                GL2D.BlendMode(GL2D.BLEND_MODE.GL2D_BLENDED);
                for (int i = frame; i < (360 + frame); i += 10)
                {
                    double px1 = Math.Sin(frame / 30.0) * 220 * Math.Cos((i * Math.PI) / 180.0);
                    double py1 = Math.Sin(frame / 80.0) * 120 * Math.Sin((i * Math.PI) / 180.0);
                    double px2 = Math.Sin(frame / 130.0) * 170 * Math.Cos(((i + 20) * Math.PI) / 180.0);
                    double py2 = Math.Sin(frame / 40.0) * 160 * Math.Sin(((i + 20) * Math.PI) / 180.0);
                    double adder = Math.Abs(4 * Math.Sin(frame / 20.0));
                    GL2D.SetColor((float)Math.Abs(Math.Sin(frame / 10.0)),
                                     (float)Math.Abs(Math.Sin(frame / 30.0)),
                                     (float)Math.Abs(Math.Sin(frame / 40.0)), 1);
                    for (int j = 0; j < adder; j++)
                    {
                        GL2D.SpriteOnLine(320 + (int)px1, 240 + (int)py1, 320 + (int)px2, 240 + (int)py2, 15 - ((int)adder * 2), atlasSprites[12]);
                    }
                }

                // animated megaman
                GL2D.BlendMode(GL2D.BLEND_MODE.GL2D_TRANS);
                GL2D.SetColor(1, 1, 1, 1);
                GL2D.SpriteRotateScale(320, 400, 0, 2, 2, GL2D.SpriteGL.FLIP_NONE, atlasSprites[1 + megaFrame]);
                
                // animated chick
                GL2D.SpriteRotateScale(100 + 150 * 0, 90, 0, 2, 2, GL2D.SpriteGL.FLIP_NONE, femaleSprites[ 0 + chickFrame]);
                GL2D.SpriteRotateScale(100 + 150 * 1, 90, 0, 2, 2, GL2D.SpriteGL.FLIP_NONE, femaleSprites[ 4 + chickFrame]);
                GL2D.SpriteRotateScale(100 + 150 * 2, 90, 0, 2, 2, GL2D.SpriteGL.FLIP_NONE, femaleSprites[ 8 + chickFrame]);
                GL2D.SpriteRotateScale(100 + 150 * 3, 90, 0, 2, 2, GL2D.SpriteGL.FLIP_NONE, femaleSprites[12 + chickFrame]);
                
                // This is our "alpha blended" controllabe plant sprite
                GL2D.BlendMode(GL2D.BLEND_MODE.GL2D_BLENDED);
                GL2D.SpriteRotateScale((int)px, (int)py, -angle, 1.0f, 1.0f, GL2D.SpriteGL.FLIP_NONE, plantSprite);

            GL2D.End2D();           // end 2D drawing mode

            this.SwapBuffers();     // copy what we draw to screen

            Thread.Sleep(1);        // sleep so that we don't hog CPU
        }


        [STAThread]
        public static void Main()
        {
            using (GL2Dexample example = new GL2Dexample())
            {
                example.Run(60.0);      // run the demo at 60 frames per second
            }
        }

    }
}
