using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Xml;
using ImageBlockz.Api;
using ImageBlockz.Core;

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

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

        public int AngleSamples
        {
            get;
            set;
        }

        public int RadiusSamples
        {
            get;
            set;
        }

        public double Minimum
        {
            get;
            set;
        }

        public double Maximum
        {
            get;
            set;
        }

        public override Bitmap Do(Bitmap bmp)
        {
            

            double centerX = bmp.Width / 2;
            double centerY = bmp.Height / 2;
 
            double minRho = Minimum;
            double maxRho = Maximum;

            int outputRho = RadiusSamples;
            int outputTheta = AngleSamples;

            double delRho = (maxRho - minRho) / outputRho;
            double delTheta = 2 * Math.PI / outputTheta;

            double x = 0;
            double y = 0;
            double xR = 0;
            double yR = 0;
            double rho = 0;
            double theta = 0;

            System.Drawing.Imaging.PixelFormat format = System.Drawing.Imaging.PixelFormat.Format24bppRgb;

            Bitmap outputBmp = new Bitmap(outputRho, outputTheta, format);

            for (int i = 0; i < outputBmp.Width; i++)
                for (int j = 0; j < outputBmp.Height; j++)
                {
                    rho = minRho + i * delRho;
                    theta = j * delTheta;

                    x = rho * Math.Cos(theta);
                    y = rho * Math.Sin(theta);

                    xR = x * (centerX -1) + centerX;
                    yR = y * (centerY -1) + centerY;

                    Color color = bmp.GetPixel((int)Math.Round(xR), (int)Math.Round(yR));
                    outputBmp.SetPixel(i, j, color); 
                }

            return outputBmp;
        }


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

            XmlElement angleSamples = XmlOperation.FloatToXml("angleSamples", AngleSamples, xmlDoc);
            XmlElement radiusSamples = XmlOperation.FloatToXml("radiusSamples", RadiusSamples, xmlDoc);
            XmlElement minimum = XmlOperation.FloatToXml("minimum", (float) Minimum, xmlDoc);
            XmlElement maximum = XmlOperation.FloatToXml("maximum", (float) Maximum, xmlDoc);

            circularSegmentation.AppendChild(angleSamples);
            circularSegmentation.AppendChild(radiusSamples);
            circularSegmentation.AppendChild(minimum);
            circularSegmentation.AppendChild(maximum);

            return circularSegmentation;
        }

        public override void FromXml(XmlNode node)
        {
            AngleSamples = (int)XmlOperation.FloatFromXml(node["angleSamples"]);
            RadiusSamples = (int)XmlOperation.FloatFromXml(node["radiusSamples"]);
            Minimum = XmlOperation.FloatFromXml(node["minimum"]);
            Maximum = XmlOperation.FloatFromXml(node["maximum"]);
        }

        public override string GetFormattedName()
        {
            return "Angle Projections";
        }


        public override string GetInfo()
        {
            return "Angle Samples: " + AngleSamples + " Radius Samples: " + RadiusSamples + " Minimum: " + Minimum + " Maximum: " + Maximum;
        }
    }
}
