using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ChamChat.Models
{
    public class Profile
    {
        public Profile(String Title, List<Step> Steps, List<Loop> Loops, List<ProfileOption> Options)
        {
            _Title = Title;
            _Steps = Steps;
            _Loops = Loops;
            _Options = Options;

            for (int i = 0; i < _Steps.Count; i++)
                _Steps[i].PK = i;
        }

        public Profile() { }


        private String _Title = "<NAME>"; public String Title { get { return _Title; } set { _Title = value; } }
        private List<Step> _Steps = new List<Step>(); public List<Step> Steps { get { return _Steps; } } // No way to set steps due to PK setting in constructor
        private List<Loop> _Loops = new List<Loop>(); public List<Loop> Loops { get { return _Loops; } }
        private List<ProfileOption> _Options = new List<ProfileOption>(); public List<ProfileOption> Options { get { return _Options; } set { _Options = value; } }
        private Int32 _ClientMIDS = 0; public Int32 ClientMIDS { get { return _ClientMIDS; } set { _ClientMIDS = value; } }


        public Double DurationMin
        {
            get
            {
                double min = 0;
                foreach (Step step in SerializedStepList)
                    min += step.DurationMin;
                return min;
            }
        }


        public Int32 Hours { get { return (int)Math.Floor(DurationMin / 60); } }
        public Int32 Minutes { get { return (int)Math.Round(DurationMin - 60 * Hours); } }


        public Double MaximumTemperature
        {
            get
            {
                double max = double.MinValue;
                foreach (Step step in _Steps)
                {
                    max = Math.Max(step.T, max);
                    max = Math.Max(step.PreTemp, max);
                    max = Math.Max(step.LimitT, max);
                }
                return max;
            }
        }



        public List<Step> SerializedStepList
        {
            get
            {
                List<Step> result = new List<Step>();
                foreach (Step step in _Steps)
                    result.Add(step);

                // Order loops with asc Last
                List<Loop> loops = _Loops.OrderByLastAsc();


                // Insert loops
                foreach (Loop loop in loops)
                {
                    // Find first index in step list of loop.first
                    int f = result.FindIndex(delegate(Step p) { return (p.PK == loop.First); });
                    int l = result.FindIndex(delegate(Step p) { return (p.PK == loop.Last); });

                    List<Step> sub = new List<Step>();
                    for (int n = 0; n < loop.N - 1; n++)
                    {
                        for (int i = f; i <= l; i++)
                        {
                            Step s = result[i].DeepClone();
                            s.PK = -99;
                            sub.Add(s);
                        }
                    }
                    int q = l - f + 1; // Insert sub after original
                    result.InsertRange(f + q, sub);
                }
                return result;
            }
        }

        public Profile(String XML)
        {
            string fp = "<" + this.GetType().Namespace + "." + this.GetType().Name + ">";
            if (!XML.Contains(fp))
                throw new Exception(fp + " tag not found!");

            try
            {
                // Title
                _Title = XML.GetTags("_Title");


                // Options
                _Options = new List<ProfileOption>();
                string[] sOptions = XML.GetTags("_Options").Split(',');
                int o = 0;
                foreach (string s in sOptions)
                    if (Int32.TryParse(s, out o))
                        _Options.Add((ProfileOption)o);


                // Loops
                _Loops = new List<Loop>();
                for (int i = 0; i < 100000; i++)
                {
                    string loop = XML.GetTags(String.Format("Loop{0:000}", i));
                    if (loop == "")
                        break;
                    else
                        _Loops.Add(new Loop(loop));

                }


                // Steps
                _Steps = new List<Step>();
                for (int i = 0; i < 100000; i++)
                {
                    string step = XML.GetTags(String.Format("Step{0:000}", i));
                    if (step == "")
                        break;
                    else
                        _Steps.Add(new Step(step));

                }

                // Client
                Int32.TryParse(XML.GetTags("_ClientMIDS"), out _ClientMIDS);


            }
            catch
            {
                throw new Exception(fp + ": could not create instance from input string!");
            }


        }

        public String XML
        {
            get
            {
                string xml = "<" + this.GetType().Namespace + "." + this.GetType().Name + ">";

                xml += "<_Title>" + _Title + "</_Title>";

                for (int i = 0; i < _Steps.Count; i++)
                    xml += String.Format("<Step{0:000}>{1}</Step{0:000}>", i, _Steps[i].XML);

                for (int i = 0; i < _Loops.Count; i++)
                    xml += String.Format("<Loop{0:000}>{1}</Loop{0:000}>", i, _Loops[i].XML);


                string o = "";
                foreach (ProfileOption option in _Options)
                    o += ((int)option).ToString() + ",";
                if (o.EndsWith(","))
                    o = o.Substring(0, o.Length - 1);
                xml += "<_Options>" + o + "</_Options>";

                xml += "<_ClientMIDS>" + _ClientMIDS.ToString() + "</_ClientMIDS>";


                xml += "</" + this.GetType().Namespace + "." + this.GetType().Name + ">";
                return xml;
            }
        }


        public override string ToString()
        {
            string s = string.Format("{0:0} steps,", _Steps.Count);
            s += string.Format("{0:0} serial steps,", SerializedStepList.Count);

            if (_Loops.Count == 0)
                s += "no loops, ";
            else
                foreach (Loop l in _Loops)
                    s += l.ToString() + ", ";

            s += String.Format("{0:0}h{1:00}", Hours, Minutes);
            return s;
        }


    }







    

}
