using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Xml;
using ImageBlockz.Operations.InOut;
using ImageBlockz.Api;
using ImageBlockz.Core;
using AForge.Imaging.Filters;
using System.Drawing.Imaging;

namespace ImageBlockz.Operations.Filters
{
    public class MidtoneLevels : AbstractOperation
    {
        public static readonly string OperationName = typeof(MidtoneLevels).FullName;

        public MidtoneLevels()
            : base(OperationType.Filter)
        {
        
        }

        public MidtoneLevels(int min, int max, int midtone)
            : this()
        {
            Max = max;
            Min = min;
            Midtone = midtone;

        }

        public float Min
        {
            set;
            get;
        }

        public float Max
        {
            set;
            get;
        }

        public float Midtone
        {
            set;
            get;
        }

        public override Bitmap Do(Bitmap bmp)
        {
            int[] lut = new int[256];

            double div1 = Midtone - Max;
            double div2 = Max - Min;

            double newMid = Math.Round(((div1) / (div2)) * 255.0);

            for (int i = 0; i < 256; i++)
            {
                if (i < Min)
                {
                    lut[i] = 0;
                }
                else if (i > Max)
                {
                    lut[i] = 255;
                }
                else if (i <= Midtone && i > Min)
                {
                    double value = Math.Round((double)((123 / (Midtone - Min)) * (i - Min)));
                    lut[i] = (int)value;
                }
                else if (i > Midtone && i <= Max)
                {
                    double value = Math.Round((double)(((255 - 123) / (Max - Midtone)) * (i - Midtone)) + 122);
                    lut[i] = (int)value;
                }
            }
            PixelFormat format = PixelFormat.Format24bppRgb;

            Bitmap newimg = new Bitmap(bmp.Width, bmp.Height, format);

            BitmapWrapper wrapperIn = new BitmapWrapper(bmp);
            BitmapWrapper wrapperOut = new BitmapWrapper(newimg);

            wrapperIn.Lock();
            wrapperOut.Lock();

            for (int x = 0; x < bmp.Width; x++)
                for (int y = 0; y < bmp.Height; y++)
                {
                    Color color = wrapperIn.GetPixel(x, y);


                    int red = lut[color.R];
                    int green = lut[color.G];
                    int blue = lut[color.B];

                    color = Color.FromArgb(red, green, blue);

                    wrapperOut.SetPixel(color, x, y);
                }

            wrapperIn.Unlock();
            wrapperOut.Unlock();

            return newimg;

        }

        public override XmlNode ToXml(XmlDocument xmlDoc)
        {
            XmlElement midtoneLevels = xmlDoc.CreateElement(OperationName);

            XmlElement min = XmlOperation.FloatToXml("min", Min, xmlDoc);
            XmlElement max = XmlOperation.FloatToXml("max", Max, xmlDoc);
            XmlElement mid = XmlOperation.FloatToXml("mid", Midtone, xmlDoc);

            midtoneLevels.AppendChild(min);
            midtoneLevels.AppendChild(max);
            midtoneLevels.AppendChild(mid);

            return midtoneLevels;
        }

        public override void FromXml(XmlNode node)
        {
            Min = XmlOperation.FloatFromXml(node["min"]);
            Max = XmlOperation.FloatFromXml(node["max"]);
            Midtone = XmlOperation.FloatFromXml(node["mid"]);
        }

        public override string GetFormattedName()
        {
            return "Contrast Stretch with Midtone";
        }


        public override string GetInfo()
        {
            return "Minimum: " + Min + " Maximum: " + Max + " Midtone: " + Midtone;
        }
    }
}
