using SDL2;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using testdrid.SdlWrapper;

namespace SDL2Demo.Screenhacks
{
    internal abstract class Processing : ScreenHack
    {
        protected Texture whiteBackground;
        protected Texture _texture;

        protected override void Setup()
        {
            Surface surface = Surface.Create(16, 16);
            surface.Fill(0xffffffff);
            whiteBackground = Texture.FromSurface(renderer, surface);

            _texture = Texture.Create(renderer, SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_STREAMING, windowRectangle.Width, windowRectangle.Height);
            _texture.SetDrawBlendMode(SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND);
            Init();
        }

        protected abstract void Init();

        protected void Background(Color c)
        {
            Surface lockAsSurface = _texture.LockAsSurface();
            lockAsSurface.Fill((uint)c.ToArgb());
            _texture.Unlock();
        }

        protected int Random(int max)
        {
            return rng.Next(max);
        }

        protected float Random(float min, float max)
        {
            if (min >= max)
                return min;
            float diff = max - min;
            return Random(diff) + min;
        }

        protected float Random(float max)
        {
            if (max == 0.0F)
                return 0.0F;

            float f = 0.0F;
            while (true)
            {
                f = rng.NextSingle() * max;
                if (f != max)
                    return f;
            }
        }

        protected int Random(int min, int max)
        {
            return rng.Next(min, max);
        }

        protected void Stroke(float paramFloat1, float paramFloat2)
        {
            ColorCalc(paramFloat1, paramFloat2);
            ColorStroke();
        }

        private void ColorStroke()
        {
            this.stroke = true;
            this.strokeR = this.calcR;
            this.strokeG = this.calcG;
            this.strokeB = this.calcB;
            this.strokeA = this.calcA;
            this.strokeRi = this.calcRi;
            this.strokeGi = this.calcGi;
            this.strokeBi = this.calcBi;
            this.strokeAi = this.calcAi;
            this.strokeColor = this.calcColor;
            this.strokeAlpha = this.calcAlpha;
            this.strokeColorObject = Color.FromArgb(strokeAi,strokeRi,strokeGi,strokeBi);
        }

        private bool stroke;
        private float strokeR, strokeG, strokeB, strokeA;
        private int strokeRi, strokeGi, strokeBi, strokeAi;
        private int strokeColor;
        private bool strokeAlpha;

        protected void ColorCalc(float paramFloat1, float paramFloat2)
        {
            /*if (paramFloat1 > this.colorModeX)
                paramFloat1 = this.colorModeX;
            if (paramFloat2 > this.colorModeA)
                paramFloat2 = this.colorModeA;
            if (paramFloat1 < 0.0F)
                paramFloat1 = 0.0F;
            if (paramFloat2 < 0.0F)
                paramFloat2 = 0.0F;*/
            this.calcR = this.colorScale ? (paramFloat1 / this.colorModeX) : paramFloat1;
            this.calcG = this.calcR;
            this.calcB = this.calcR;
            this.calcA = this.colorScale ? (paramFloat2 / this.colorModeA) : paramFloat2;
            this.calcRi = (int)(this.calcR);
            this.calcGi = (int)(this.calcG);
            this.calcBi = (int)(this.calcB);
            this.calcAi = (int)(this.calcA);
            this.calcColor = this.calcAi << 24 | this.calcRi << 16 | this.calcGi << 8 | this.calcBi;
            if (this.calcAi != 255)
                this.calcAlpha = false;
            this.calcAlpha = true;
        }

        private float colorModeX, colorModeA, calcR, calcG, calcB, calcA;

        private bool colorScale;

        private int calcRi, calcGi, calcBi, calcAi, calcColor;

        private bool calcAlpha;
        private Color strokeColorObject;
        
        protected int colorMode = 1;
        private float colorModeY, colorModeZ;

        protected void Point(float x, float y)
        {
            int ix = (int)x;
            int iy = (int)y;
            _texture.Lock();
            _texture.SetPixel(ix, iy, strokeColorObject.A, strokeColorObject.R, strokeColorObject.G, strokeColorObject.B);
            _texture.Unlock();
        }

        protected void Stroke(float r, float g, float b, float a)
        {
            ColorCalc(r, g, b, a);
            ColorStroke();
        }

        protected void ColorCalc(float paramFloat1, float paramFloat2, float paramFloat3, float paramFloat4)
        {
            float f1, f2, f3, f4, f5;
            /*
            if (paramFloat1 > this.colorModeX)
                paramFloat1 = this.colorModeX;
            if (paramFloat2 > this.colorModeY)
                paramFloat2 = this.colorModeY;
            if (paramFloat3 > this.colorModeZ)
                paramFloat3 = this.colorModeZ;
            if (paramFloat4 > this.colorModeA)
                paramFloat4 = this.colorModeA;
            if (paramFloat1 < 0.0F)
                paramFloat1 = 0.0F;
            if (paramFloat2 < 0.0F)
                paramFloat2 = 0.0F;
            if (paramFloat3 < 0.0F)
                paramFloat3 = 0.0F;
            if (paramFloat4 < 0.0F)
                paramFloat4 = 0.0F;*/
            switch (this.colorMode)
            {
                case 1:
                    if (this.colorScale)
                    {
                        this.calcR = paramFloat1 / this.colorModeX;
                        this.calcG = paramFloat2 / this.colorModeY;
                        this.calcB = paramFloat3 / this.colorModeZ;
                        this.calcA = paramFloat4 / this.colorModeA;
                        break;
                    }
                    this.calcR = paramFloat1;
                    this.calcG = paramFloat2;
                    this.calcB = paramFloat3;
                    this.calcA = paramFloat4;
                    break;
                case 3:
                    paramFloat1 /= this.colorModeX;
                    paramFloat2 /= this.colorModeY;
                    paramFloat3 /= this.colorModeZ;
                    this.calcA = this.colorScale ? (paramFloat4 / this.colorModeA) : paramFloat4;
                    if (paramFloat2 == 0.0F)
                    {
                        this.calcR = this.calcG = this.calcB = paramFloat3;
                        break;
                    }
                    f1 = (paramFloat1 - (int)paramFloat1) * 6.0F;
                    f2 = f1 - (int)f1;
                    f3 = paramFloat3 * (1.0F - paramFloat2);
                    f4 = paramFloat3 * (1.0F - paramFloat2 * f2);
                    f5 = paramFloat3 * (1.0F - paramFloat2 * (1.0F - f2));
                    switch ((int)f1)
                    {
                        case 0:
                            this.calcR = paramFloat3;
                            this.calcG = f5;
                            this.calcB = f3;
                            break;
                        case 1:
                            this.calcR = f4;
                            this.calcG = paramFloat3;
                            this.calcB = f3;
                            break;
                        case 2:
                            this.calcR = f3;
                            this.calcG = paramFloat3;
                            this.calcB = f5;
                            break;
                        case 3:
                            this.calcR = f3;
                            this.calcG = f4;
                            this.calcB = paramFloat3;
                            break;
                        case 4:
                            this.calcR = f5;
                            this.calcG = f3;
                            this.calcB = paramFloat3;
                            break;
                        case 5:
                            this.calcR = paramFloat3;
                            this.calcG = f3;
                            this.calcB = f4;
                            break;
                    }
                    break;
            }
            this.calcRi = (int)(1.0f * this.calcR);
            this.calcGi = (int)(1.0f * this.calcG);
            this.calcBi = (int)(1.0f * this.calcB);
            this.calcAi = (int)(1.0f * this.calcA);
            this.calcColor = this.calcAi << 24 | this.calcRi << 16 | this.calcGi << 8 | this.calcBi;
            if (this.calcAi != 255)
                this.calcAlpha = false;
            this.calcAlpha = true;
        }

        protected float Red(int paramInt)
        {
            float f = (paramInt >> 16 & 0xFF);
            if (this.colorRgb255)
                return f;
            return f / 255.0F * this.colorModeX;
        }

        protected bool colorRgb255;
    }
}
