using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.IO;
using System.Windows.Forms;

namespace EduNetworkBuilder
{
    /// <summary>
    /// A class holding a project that needs to be done as either a test, quiz, or homework
    /// </summary>
    [Serializable]
    public class SchoolworkClass
    {
        public Network theProject = null;
        /// <summary>
        /// The name of the project.  Homework3, Quiz 4, etc.
        /// </summary>
        public string Name = "";

        /// <summary>
        /// The Suggested filename for this homework.  The Name + ".eduh"
        /// </summary>
        public string FileName { get { return Name + ".eduh"; } }
        /// <summary>
        /// The short description of the project.
        /// </summary>
        public string Description = "";
        /// <summary>
        /// The class to which this project belongs.  If the student is using this for multiple classes,
        /// but more likely just for the teacher to organize things with.
        /// </summary>
        public string Class = "";
        /// <summary>
        /// The date / time that the project is due.
        /// </summary>
        public DateTime DueDate;

        public bool isMaster = false; //Is this the original project?  If so, we never replace it.

        public bool IsSumbitted = false; //Is the student submitting this?  If so, date-stamp it and lock it.
        public bool IsGraded = false;
        public DateTime SaveDate; //The date this file was saved.
        public UInt64 ThisID { get; protected set; }

        public HomeworkSolvedStatus HomeworkStatus = HomeworkSolvedStatus.NeverChecked;


        protected SchoolworkClass() { }

        public SchoolworkClass(XmlNode TheNode)
        {
            List<SchoolworkClass> WhatIs = Load(TheNode);
            if (WhatIs.Count > 0)
            {
                SchoolworkClass.Clone(WhatIs[0], this);
                //Move the packet messages across.  They do not get cloned.
                //We do this so we can store the results of an automated test
                if(WhatIs[0].theProject != null && WhatIs[0].theProject.CountMessages() > 0)
                {
                    foreach(PacketMessage one in WhatIs[0].theProject.GetAllMessages())
                    {
                        theProject.AddMessage(one);
                    }
                }
            }
        }

        public SchoolworkClass(string  FileName)
        {
            Load(FileName);
        }

        public SchoolworkClass(Network ToAdd, PersonClass WhoFor)
        {
            if(WhoFor != null && WhoFor.UserSettings != null)
                ThisID = WhoFor.UserSettings.IssueID();
            theProject = ToAdd.Clone();
            Name = theProject.PuzzleName;
            Description = theProject.PuzzleName;
            isMaster = true;
        }

        public SchoolworkClass Clone()
        {
            SchoolworkClass dest = new SchoolworkClass();
            Clone(this, dest);
            return dest;
        }

        public static void Clone(SchoolworkClass source, SchoolworkClass dest)
        {
            dest.ThisID = source.ThisID;
            dest.Class = source.Class;
            dest.Description = source.Description;
            dest.DueDate = source.DueDate;
            dest.isMaster = source.isMaster;
            dest.IsSumbitted = source.IsSumbitted;
            dest.Name = source.Name;
            dest.SaveDate = source.SaveDate;
            dest.theProject = source.theProject.Clone();
            dest.IsGraded = source.IsGraded;
        }

        /// <summary>
        /// Basically for sorting.  First by class name, then due date, and then save date
        /// </summary>
        /// <param name="WhatTo"></param>
        /// <returns></returns>
        public int Compare(SchoolworkClass WhatTo)
        {
            int diff = Class.CompareTo(WhatTo.Class);
            if (diff != 0) return diff;

            diff = DueDate.CompareTo(WhatTo.DueDate);
            if (diff != 0) return diff;

            return SaveDate.CompareTo(WhatTo.SaveDate);
         }

        #region Load and Save 
        //Load and save functions
        public void Load(string filename)
        {
            XmlDocument xmlDoc = new XmlDocument();

            if (File.Exists(filename))
            {
                xmlDoc.Load(filename);
                List<SchoolworkClass>  results = Load(xmlDoc);
                if (results.Count > 0) Clone(results[0], this);
            }
        }

        public static List<SchoolworkClass> LoadMultiple(string filename)
        {
            XmlDocument xmlDoc = new XmlDocument();
            List<SchoolworkClass> results = new List<SchoolworkClass>();
            if (File.Exists(filename))
            {
                try
                {
                    xmlDoc.Load(filename);
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.ToString());
                    return results;  //return an empty list
                }
                results.AddRange(Load(xmlDoc));
            }
            return results;
        }

        public static List<SchoolworkClass> Load(XmlNode TheNode)
        {
            SchoolworkClass currentOne = new SchoolworkClass();
            List<SchoolworkClass> ThisList = new List<SchoolworkClass>();
            bool AddedList = false;
            foreach (XmlNode Individual in TheNode.ChildNodes)
            {
                XmlNodeType myNodetype = Individual.NodeType;
                if (myNodetype == XmlNodeType.Element)
                {
                    switch (Individual.Name.ToLower())
                    {
                        case "edunetworkbuilderschoolwork":
                        case "schoolwork":
                            ThisList.AddRange(Load(Individual));
                            AddedList = true;
                            break;
                        case "id":
                            UInt64 tID;
                            UInt64.TryParse(Individual.InnerText, out tID);
                            currentOne.ThisID = tID;
                            break;
                        case "name":
                            currentOne.Name = Individual.InnerText;
                            break;
                        case "description":
                            currentOne.Description = Individual.InnerText;
                            break;
                        case "class":
                            currentOne.Class = Individual.InnerText;
                            break;
                        case "duedate":
                            DateTime.TryParse(Individual.InnerText, out currentOne.DueDate); 
                            break;
                        case "savedate":
                            DateTime.TryParse(Individual.InnerText, out currentOne.SaveDate);
                            break;
                        case "homeworkstatus":
                            currentOne.HomeworkStatus = NB.ParseEnum<HomeworkSolvedStatus>(Individual.InnerText);
                            break;
                        case "ismaster":
                            bool.TryParse(Individual.InnerText, out currentOne.isMaster);
                            break;
                        case "isgraded":
                            bool.TryParse(Individual.InnerText, out currentOne.IsGraded);
                            break;
                        case "issubmitted":
                            bool.TryParse(Individual.InnerText, out currentOne.IsSumbitted);
                            break;
                        case "network":
                            currentOne.theProject = new Network();
                            currentOne.theProject.Load(Individual, "",false,true);
                            break;
                    }
                }
            }
            if (!AddedList) ThisList.Add(currentOne);

            return ThisList;
        }

        public void Save(string filename)
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.NewLineOnAttributes = true;
            XmlWriter writer = XmlWriter.Create(filename, settings);

            //Now we write the file:
            writer.WriteStartDocument();
            writer.WriteStartElement("EduNetworkBuilderSchoolwork");
            writer.WriteComment("This is a schoolwork file for EduNetworkBuilder.");
            Save(writer);
            writer.WriteEndElement();
            writer.WriteEndDocument();
            writer.Flush();
            writer.Close();
        }

        public static void Save(List<SchoolworkClass> homeworks, string filename)
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.NewLineOnAttributes = true;
            XmlWriter writer = XmlWriter.Create(filename, settings);

            //Now we write the file:
            writer.WriteStartDocument();
            writer.WriteStartElement("EduNetworkBuilderSchoolwork");
            writer.WriteComment("This is a schoolwork file for EduNetworkBuilder.");
            foreach (SchoolworkClass swc in homeworks)
            {
                swc.Save(writer);
            }
            writer.WriteEndElement();
            writer.WriteEndDocument();
            writer.Flush();
            writer.Close();
        }

        public void ChangeID(PersonClass WhoFor)
        {
            if (WhoFor != null && WhoFor.UserSettings != null)
                ThisID = WhoFor.UserSettings.IssueID();
        }

        public HomeworkSolvedStatus CheckThatHomeworkIsSolved()
        {
            if(theProject != null)
            {
                HomeworkStatus = theProject.CheckThatHomeworkIsSolved();
            }
            return HomeworkStatus;
        }

        public void Save(XmlWriter writer)
        {
            //Save the language name
            //save the number of items
            //Save all the items
            writer.WriteStartElement("schoolwork");
            writer.WriteElementString("ID", ThisID.ToString());
            writer.WriteElementString("Name", Name);
            writer.WriteElementString("Description", Description);
            writer.WriteElementString("Class", Class);
            writer.WriteElementString("DueDate", DueDate.ToString());
            writer.WriteElementString("SaveDate", SaveDate.ToString());
            writer.WriteElementString("IsMaster", isMaster.ToString());
            writer.WriteElementString("IsGraded", IsGraded.ToString());
            if (HomeworkStatus != HomeworkSolvedStatus.NeverChecked)
                writer.WriteElementString("HomeworkStatus", HomeworkStatus.ToString());
            writer.WriteElementString("IsSubmitted", IsSumbitted.ToString());
            if (theProject != null) theProject.Save(writer,true,true);//Save the messages also.
            writer.WriteEndElement();
        }
        #endregion
    }
}