using System;
using System.Xml;
using System.IO;
using System.Text;
using System.Collections.Generic;
using Orienteering.Standard;

namespace Orienteering.Competition {
    public class Stage {
        internal Orienteering.Data.Stage data;

        private void SaveNew(DataBase dataBase) {
            try {
                Competition.Stage(Number, dataBase);
                throw new AlreadyExists();
            }
            catch (DoesntExist) {
                this.Save(dataBase);
            }
        }

        public Stage(int num, string organiz, Competition comp, DataBase dataBase) {
            data = new Orienteering.Data.Stage(num, organiz, comp.data);
            SaveNew(dataBase);
        }

        public Stage(XmlNode xml, Competition comp, DataBase dataBase) {
            data = new Orienteering.Data.Stage();
            Competition = comp;

            foreach (XmlAttribute xmlattr in xml.Attributes) {
                if (xmlattr.Name == "number")
                    Number = Convert.ToInt32(xmlattr.Value);
                if (xmlattr.Name == "organizer")
                    Organizer = xmlattr.Value;
                if (xmlattr.Name == "mapPath")
                    MapPath = xmlattr.Value;
                if (xmlattr.Name == "startTime")
                    StartTime = Convert.ToDateTime(xmlattr.Value);
            }
            SaveNew(dataBase);

            foreach (XmlNode node in xml.ChildNodes) 
                if (node.Name == "objects")
                    foreach (XmlNode node1 in node.ChildNodes) {
                        if (node1.Name == "start")
                            AddObject(new Start(node1, this), dataBase);
                        if (node1.Name == "control")
                            AddObject(new Control(node1, this), dataBase);
                        if (node1.Name == "finish")
                            AddObject(new Finish(node1, this), dataBase);
                    }

            foreach (XmlNode node in xml.ChildNodes) 
                if (node.Name == "courses")
                    foreach (XmlNode node1 in node.ChildNodes)
                        if (node1.Name == "course")
                            new Course(node1, this, dataBase);

        }

        public DateTime StartTime {
            get { return data.StartTime; }
            set { data.StartTime = value; }
        }
        
        public string MapPath {
            get { return data.MapPath; }
            set { data.MapPath = value; }
        }

        public int Number {
            get { return data.Number; }
            set { data.Number = value; }
        }

        public string Organizer {
            get { return data.Organizer; }
            set { data.Organizer = value; }
        }

        public Competition Competition {
            get { return new Competition(data.Competition); }
            set { data.Competition = value.data; } 
        }

        public Stage(Orienteering.Data.Stage _data) {
            data = _data;
        }

        public void Save(DataBase dataBase) {
            data.Save(dataBase.data);
        }

        public void AddCourse(Course course, DataBase dataBase) {
            data.AddCourse(course.data, dataBase.data);
        }

        public void AddObject(Object obj, DataBase dataBase) {
            data.AddObject(obj.data, dataBase.data);
        }

        public List<Object> Objects(DataBase dataBase) {
            List<Object> res = new List<Object>();
            foreach (Orienteering.Data.Object obj in data.Objects(dataBase.data)) {
                if (obj is Orienteering.Data.Start)
                    res.Add(new Start(obj as Orienteering.Data.Start));
                if (obj is Orienteering.Data.Control)
                    res.Add(new Control(obj as Orienteering.Data.Control));
                if (obj is Orienteering.Data.Finish)
                    res.Add(new Finish(obj as Orienteering.Data.Finish));
            }
            return res;
        }

        public List<Course> Courses(DataBase dataBase) {
            List<Course> res = new List<Course>();
            foreach (Orienteering.Data.Course course in data.Courses(dataBase.data))
                res.Add(new Course(course));
            return res;
        }

        public List<Start> Starts(DataBase dataBase) {
            List<Start> res = new List<Start>();
            foreach (Orienteering.Data.Start start in data.Starts(dataBase.data))
                res.Add(new Start(start));
            return res;
        }

        public List<Finish> Finishes(DataBase dataBase) {
            List<Finish> res = new List<Finish>();
            foreach (Orienteering.Data.Finish finish in data.Finishes(dataBase.data))
                res.Add(new Finish(finish));
            return res;
        }

        public List<Control> Controls(DataBase dataBase) {
            List<Control> res = new List<Control>();
            foreach (Orienteering.Data.Control control in data.Controls(dataBase.data))
                res.Add(new Control(control));
            return res;
        }

        public List<Category> Categories(DataBase dataBase) {
            List<Category> res = new List<Category>();
            foreach (Orienteering.Data.Category category in data.Categories(dataBase.data))
                res.Add(new Category(category));
            return res;
        }

        public Category Category(string name, DataBase dataBase) {
            return new Category(data.Category(name, dataBase.data));
        }

        public Course Course(string name, DataBase dataBase) {
            return new Course(data.Course(name, dataBase.data));
        }

        public Start Start(int num, DataBase dataBase) {
            return new Start(data.Start(num, dataBase.data));
        }

        public Control Control(int num, DataBase dataBase) {
            return new Control(data.Control(num, dataBase.data));
        }

        public Finish Finish(int num, DataBase dataBase) {
            return new Finish(data.Finish(num, dataBase.data));
        }

        public Result Result(string name, DataBase dataBase) {
            return new Result(data.Result(name, dataBase.data));
        }

        public XmlNode Xml(XmlDocument xml, DataBase dataBase) {
            XmlNode res = xml.CreateNode("element", "stage", "");
            XmlAttribute numberAttr = (XmlAttribute)xml.CreateNode("attribute", "number", "");
            numberAttr.Value = Number.ToString();
            res.Attributes.Append(numberAttr);

            XmlAttribute organizerAttr = (XmlAttribute)xml.CreateNode("attribute", "organizer", "");
            organizerAttr.Value = Organizer;
            res.Attributes.Append(organizerAttr);

            XmlAttribute mapPathAttr = (XmlAttribute)xml.CreateNode("attribute", "mapPath", "");
            mapPathAttr.Value = MapPath;
            res.Attributes.Append(mapPathAttr);

            XmlAttribute startTimeAttr = (XmlAttribute)xml.CreateNode("attribute", "startTime", "");
            startTimeAttr.Value = Convert.ToString(StartTime);
            res.Attributes.Append(startTimeAttr);

            XmlNode obj = xml.CreateNode("element", "objects", "");
            foreach (Object k in Objects(dataBase))
                obj.AppendChild(k.Xml(xml));
            res.AppendChild(obj);

            XmlNode cour = xml.CreateNode("element", "courses", "");
            foreach (Course course in Courses(dataBase))
                cour.AppendChild(course.Xml(xml, dataBase));
            res.AppendChild(cour);

            return res;
        }

        public void StartList(string path, DataBase dataBase) {
            XmlDocument file = new XmlDocument(); 
            XmlNode tableElement = file.CreateNode("element", "table", "");
            file.AppendChild(tableElement);

            foreach (Category category in Categories(dataBase))
                tableElement.AppendChild(category.StartList(file, dataBase));
            
            FileStream fs1 = File.Create(path);
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.OmitXmlDeclaration = false;
            settings.Encoding = Encoding.UTF8;

            XmlWriter writer = XmlWriter.Create(fs1, settings);
            file.WriteTo(writer);
            writer.Flush();
            fs1.Close();
        }

        public void Results(string path, DataBase dataBase) {
            XmlDocument file = new XmlDocument(); 
            XmlNode tableElement = file.CreateNode("element", "table", "");
            file.AppendChild(tableElement);

            foreach (Category category in Categories(dataBase))
                tableElement.AppendChild(category.Results(file, dataBase));
            
            FileStream fs1 = File.Create(path);
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.OmitXmlDeclaration = false;
            settings.Encoding = Encoding.UTF8;

            XmlWriter writer = XmlWriter.Create(fs1, settings);
            file.WriteTo(writer);
            writer.Flush();
            fs1.Close();
        }
    }
}
