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;

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

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

        public Convolution(int[,] kernel)
            :this()
        {
            Kernel = kernel;
        }

        public int[,] Kernel
        {
            get;
            set;
        }

        public override Bitmap Do(Bitmap bmp)
        {
            AForge.Imaging.Filters.Convolution filter = new AForge.Imaging.Filters.Convolution(Kernel);            
            return filter.Apply(bmp);
        }

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

            XmlElement topleft = XmlOperation.FloatToXml("topleft", Kernel[0, 0], xmlDoc);
            XmlElement topmid = XmlOperation.FloatToXml("topmid", Kernel[0, 1], xmlDoc);
            XmlElement topright = XmlOperation.FloatToXml("topright", Kernel[0, 2], xmlDoc);

            XmlElement midleft = XmlOperation.FloatToXml("midleft", Kernel[1, 0], xmlDoc);
            XmlElement midmid = XmlOperation.FloatToXml("midmid", Kernel[1, 1], xmlDoc);
            XmlElement midright = XmlOperation.FloatToXml("midright", Kernel[1, 2], xmlDoc);

            XmlElement bottomleft = XmlOperation.FloatToXml("bottomleft", Kernel[2, 0], xmlDoc);
            XmlElement bottommid = XmlOperation.FloatToXml("bottommid", Kernel[2, 1], xmlDoc);
            XmlElement bottomright = XmlOperation.FloatToXml("bottomright", Kernel[2, 2], xmlDoc);

            convolution.AppendChild(topleft);
            convolution.AppendChild(topmid); 
            convolution.AppendChild(topright);

            convolution.AppendChild(midleft);
            convolution.AppendChild(midmid);
            convolution.AppendChild(midright);

            convolution.AppendChild(bottomleft);
            convolution.AppendChild(bottommid);
            convolution.AppendChild(bottomright);

            return convolution;
        }

        public override void FromXml(XmlNode node)
        {
            int[,] kernel = new int[3,3];

            kernel[0, 0] = (int)XmlOperation.FloatFromXml(node["topleft"]);
            kernel[0, 1] = (int)XmlOperation.FloatFromXml(node["topmid"]);
            kernel[0, 2] = (int)XmlOperation.FloatFromXml(node["topright"]);

            kernel[1, 0] = (int)XmlOperation.FloatFromXml(node["midleft"]);
            kernel[1, 1] = (int)XmlOperation.FloatFromXml(node["midmid"]);
            kernel[1, 2] = (int)XmlOperation.FloatFromXml(node["midright"]);

            kernel[2, 0] = (int)XmlOperation.FloatFromXml(node["bottomleft"]);
            kernel[2, 1] = (int)XmlOperation.FloatFromXml(node["bottommid"]);
            kernel[2, 2] = (int)XmlOperation.FloatFromXml(node["bottomright"]);

            Kernel = kernel;
        }

        public override string GetFormattedName()
        {
            return "User defined Convolution: ";
        }

        public override string GetInfo()
        {
            return "Parameters hidden.";
        }
    }
}
