using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

using FormulaEditor;
using FormulaEditorUI;

namespace DataPerformerUI
{
    public partial class FormDerivationCalculator : Form
    {
        private MathFormulaDrawable derivFormula;
        private Rectangle derivRect;
        private Image derivImage;
        private Point pointDeriv;
        private bool accepted = false;
        private Pen rectPen = new Pen(Color.Black);
        private Brush fillBrush = new SolidBrush(Color.FromArgb(216, 203, 187));
        private FormulaEditorPanel panel;
        private Panel panelBase;



        public FormDerivationCalculator()
        {
            InitializeComponent();
            panelBase = panelDesktopCenter;
            ResourceService.Resources.LoadControlResources(this);
            panel = new FormulaEditorPanel();
            panel.Left = 0;
            panel.Top = 0;
            panel.Width = 1200;
            panel.Height = 300;
            panelBase.Controls.Add(panel);
            panel.Prepare();
            openFileDialogEditor.InitialDirectory =
                ResourceService.Resources.CurrentDirectory + "\\Functions";
            saveFileDialogEditor.InitialDirectory = openFileDialogEditor.InitialDirectory;

        }

        public FormDerivationCalculator(string s)
        {

            InitializeComponent();
            panelBase = panelDesktopCenter;

            ResourceService.Resources.LoadControlResources(this);
            panel = new FormulaEditorPanel();
            panel.Left = 0;
            panel.Top = 0;
            panel.Width = 1200;

            panel.Height = 300;

            panelDeriv.Top = panel.Top + panel.Height + 20;
            panelDeriv.Left = panel.Left;
            panelDeriv.Width = panel.Width;
            panelDeriv.Height = 300;//nel.Height;
            derivRect = new Rectangle(80, 20, 1100, panelDeriv.Height - 40);
            pointDeriv = new Point(derivRect.Left + 20, derivRect.Top + derivRect.Height / 2);
            derivImage = new Bitmap(panelDeriv.Width, panelDeriv.Height);
            Graphics g = Graphics.FromImage(derivImage);
            g.FillRectangle(new SolidBrush(Color.LightGray), 0, 0, derivImage.Width, derivImage.Height);
            g.DrawRectangle(new Pen(Color.Black), 0, 0, derivImage.Width - 1, derivImage.Height - 1);
            Font f = new Font("Serif", MathSymbolFactory.Sizes[0], FontStyle.Bold | FontStyle.Italic);
            int delta = 15;
            Brush bBrush = new SolidBrush(Color.Black);
            g.DrawString("f' = ", f, bBrush, 10, pointDeriv.Y + delta);
            g.Dispose();
            textBoxDerivType.Left = 20;
            textBoxDerivType.Top = pointDeriv.Y + 35;
            panelBase.Controls.Add(panel);
            string[] symbols = new string[] { "abcdefghijklmnopqrstuvwxyz" };
            panel.Prepare(s, 4, null, null);
            openFileDialogEditor.InitialDirectory =
                ResourceService.Resources.CurrentDirectory + "\\Functions";
            saveFileDialogEditor.InitialDirectory = openFileDialogEditor.InitialDirectory;
        }


        public string Formula
        {
            get
            {
                return panel.Performer.Formula.FormulaString;
            }
            set
            {
                panel.Performer.Formula =
                    new MathFormulaDrawable(MathFormula.FromString(MathSymbolFactory.Sizes, value), DrawableConverter.Object);
                panel.Performer.DrawFormula();//.Prepare(s);
            }
        }

        public bool Accepted
        {
            get
            {
                return accepted;
            }
        }

        private void load(string filename)
        {
            try
            {
                /*XmlDocument doc = new XmlDocument();
                /*XmlReader reader = new XmlTextReader(filename);
                doc.Load(reader);
                reader.Close();
                XmlElement el = doc.GetElementsByTagName("Function")[0] as XmlElement;
                Formula = el.Attributes["Formula"].Value;*/
                /*doc.Load(filename);
                XmlCDataSection s = doc.DocumentElement.FirstChild as XmlCDataSection;*/
                System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
                    formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
                Stream stream = File.OpenRead(filename);
                MathFormula f = formatter.Deserialize(stream) as MathFormula;
                stream.Close();
                f.Post();
                Formula = f.FormulaString;
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(this, ex.Message);
            }
        }

        private void save(string filename)
        {
            /*	XmlDocument doc = new XmlDocument();
                doc.LoadXml("<?xml version=\"1.0\"?>" + "<Root>" + "</Root>");
                XmlCDataSection section = doc.CreateCDataSection("Data");
                section.InnerText = Formula;
                doc.DocumentElement.AppendChild(section);
                doc.Save(filename);
                /*XmlElement element = doc.CreateElement("Function");
                XmlAttribute f = doc.CreateAttribute("Formula");
                f.Value = Formula;
                element.Attributes.Append(f);
                XmlNode nl = doc.DocumentElement;
                nl.AppendChild(element);
                if (doc != null)
                {
                    XmlWriter writer = new XmlTextWriter(filename, new System.Text.UTF8Encoding());
                    doc.WriteContentTo(writer);
                    writer.Flush();
                    writer.Close();
                }*/
            //doc.WriteTo(.WriteContentTo(.WriteTo(.WriteContentTo(

            BinaryFormatter formatter = new BinaryFormatter();
            string s = Formula;
            byte[] b = new byte[s.Length];
            for (int i = 0; i < b.Length; i++)
            {
                b[i] = (byte)s[i];
            }

            Stream stream = File.OpenWrite(filename);
            stream.Write(b, 0, b.Length);
            stream.Close();
        }

        private void buttonOK_Click(object sender, EventArgs e)
        {
            try
            {
                MathFormula formula = panel.Performer.Formula;
                MathFormula f = formula.FullTransform;
                //new FormulaTree(f);
            }
            catch (System.Exception ex)
            {
                string err = ResourceService.Resources.GetControlResource("Error");
                /*
                if (resources != null)
                {
                    string rErr = resources.GetString("Error");
                    if (rErr != null)
                    {
                        err = rErr;
                    }
                }*/
                MessageBox.Show(this, ex.Message, err, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            accepted = true;
            Dispose();
        }

        private void paintDeriv()
        {
            Graphics g = Graphics.FromImage(derivImage);
            g.FillRectangle(fillBrush, derivRect.Left, derivRect.Top, derivRect.Width, derivRect.Height);
            if (derivFormula != null)
            {
                derivFormula.Draw(g);
            }
            g.DrawRectangle(rectPen, derivRect.Left, derivRect.Top, derivRect.Width - 1, derivRect.Height - 1);
        }


        private void buttonCancel_Click(object sender, EventArgs e)
        {
            Dispose();
        }

        private void buttonCalc_Click(object sender, EventArgs e)
        {
           // try
           // {
                string fs = panel.Performer.Formula.FormulaString;
                MathFormula f = MathFormula.FromString(panel.Performer.Formula.Sizes, fs);
                f = f.FullTransform;
                /*FormulaTree tree = new FormulaTree(f);
                FormulaTree der = tree.Deriv(textBoxDerivType.Text);
                der.SimplifyAll();
                derivFormula = der.GetFormula(0, FormulaEditorPanel.sizes);*/
                ObjectFormulaTree tree = new ObjectFormulaTree(f, ElementaryFunctionsCreator.Object);
                ObjectFormulaTree der = DerivationPerformer.Derivation(tree, textBoxDerivType.Text);
                der = ElementaryFormulaSimplification.Object.Simplify(der);//der.SimplifyAll();
                MathFormula form = FormulaCreator.CreateFormula(der, (byte)0, MathSymbolFactory.Sizes);

                form.Simplify();

                derivFormula = new MathFormulaDrawable(form, DrawableConverter.Object);
                derivFormula.Position = pointDeriv;
                derivFormula.CalculateFullRelativeRectangle();
                derivFormula.CalculatePositions();
                paintDeriv();
                Refresh();
        /*    }
            catch (System.Exception ex)
            {
                MessageBox.Show(this, ex.Message);
            }*/

        }

        private void panelDeriv_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.DrawImage(derivImage, 0, 0);
        }
    }
}