using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using OrComp = Orienteering.Competition;
using Gtk;

namespace Orienteering.GUI {
    public class Stage {
        internal Orienteering.Competition.Stage data;
        private string drawCourse;
        internal System.Drawing.Image map;
        public Stage(Orienteering.Competition.Stage _data) {
            data = _data;
            drawCourse = null;
            try {
                map = System.Drawing.Image.FromFile(MapPath);
            }
            catch {
                if (MapPath != null)
                    Standard.Error("Chyba pri otváraní súboru s mapou");
            }
        }

        public string MapPath {
            get { return data.MapPath; }
            set {
                try {
                    map = System.Drawing.Image.FromFile(value);
                    data.MapPath = value;
                }
                catch {
                    if (value != null) Standard.Error("Chyba pri otváraní súboru s mapou");
                }
            }
        }

        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 (OrComp.Object obj in data.Objects(dataBase.data)) {
                if (obj is OrComp.Start)
                    res.Add(new Start(obj as OrComp.Start));
                if (obj is OrComp.Control)
                    res.Add(new Control(obj as OrComp.Control));
                if (obj is OrComp.Finish)
                    res.Add(new Finish(obj as OrComp.Finish));
            }
            return res;
        }

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

        public void Draw(System.Drawing.Graphics gr, DataBase dataBase) {
            if (Config.DrawMap)
                gr.DrawImage(map, 0, 0);
            else
                gr.Clear(System.Drawing.Color.White);

            Dictionary<int, bool> set = new Dictionary<int, bool>();
            if (drawCourse != null) {
                Config.Style = Config.PenStyle.Dark;
                Config.FStyle = Config.FontStyle.Big;
                Course course = this.Course(drawCourse, dataBase);
                course.Draw(gr);
                foreach (Object obj in course.Objects) {
                    int tmp = 3*obj.Number;
                    if (obj is Control) tmp++;
                    if (obj is Finish) tmp += 2;
                    set[tmp] = true;
                }
            }

            Config.Style = Config.PenStyle.Light;
            Config.FStyle = Config.FontStyle.Small;
            foreach (Object obj in Objects(dataBase)) {
                int q = obj.Number*3;
                if (obj is Control) q++;
                if (obj is Finish) q += 2;

                if (!set.ContainsKey(q)) {
                    obj.Draw(gr, Math.PI);
                    obj.DrawNumber(gr, obj.Number, Math.PI/4);
                }
            }

        }

        public ComboBox Starts(DataBase dataBase) {
            ComboBox combo = ComboBox.NewText();
            List<OrComp.Start> starts = data.Starts(dataBase.data);
            foreach (OrComp.Start start in starts)
                combo.AppendText(start.Number.ToString());
            return combo;
        }

        public ComboBox Finishes(DataBase dataBase) {
            ComboBox combo = ComboBox.NewText();
            List<OrComp.Start> starts = data.Starts(dataBase.data);
            foreach (OrComp.Start start in starts)
                combo.AppendText(start.Number.ToString());
            return combo;
        }

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

        private ListStore CourseListStore;
        private TreeView tree;
        private List<Orienteering.Competition.Course> courses;
        private DataBase db;
        public VBox Courses(DataBase dataBase)  {
            db = dataBase;
            courses = data.Courses(dataBase.data);

            CourseListStore = new ListStore(typeof(Orienteering.Competition.Course));
            foreach (OrComp.Course course in courses)
                CourseListStore.AppendValues(course);

            tree = new TreeView(CourseListStore);
            tree.EnableGridLines = TreeViewGridLines.Both;
            tree.AppendColumn(
                    Standard.treeColText("Meno", new TreeCellDataFunc(RenderName), EditName) );
            tree.AppendColumn(
                    Standard.treeColText("Dĺžka (km)", new TreeCellDataFunc(RenderLength), null) );
            tree.AppendColumn(
                    Standard.treeColRadio("Vykreslená trať", new TreeCellDataFunc(RenderDrawn), EditDrawn) );

            tree.RulesHint = true;
            Viewport viePo = new Viewport();
            viePo.Add(tree);
            ScrolledWindow viewer = new ScrolledWindow();
            viewer.Add(viePo);

            VBox vbox1 = new VBox();
            vbox1.PackStart(viewer, true, true, 2);

            return vbox1;
        }

        private void RenderLength(TreeViewColumn column, CellRenderer cell,
                TreeModel model, TreeIter iter) {
            OrComp.Course course = (OrComp.Course)model.GetValue(iter, 0);
            (cell as CellRendererText).Text = (course.Length/1500*2.54).ToString();
        }

        private void RenderName(TreeViewColumn column, CellRenderer cell,
                TreeModel model, TreeIter iter) {
            OrComp.Course course = (OrComp.Course)model.GetValue(iter, 0);
            (cell as CellRendererText).Text = course.Name;
        }
        private void EditName(object o, EditedArgs args) {
            TreeIter iter;
            CourseListStore.GetIter (out iter, new TreePath (args.Path));
            OrComp.Course course = (OrComp.Course)CourseListStore.GetValue(iter, 0);
            course.Name = args.NewText;
            course.Save(db.data);
        }

        private void RenderDrawn(TreeViewColumn column, CellRenderer cell,
                TreeModel model, TreeIter iter) {
            OrComp.Course course = (OrComp.Course)model.GetValue(iter, 0);
            (cell as CellRendererToggle).Active = (drawCourse != null && drawCourse == course.Name);
        }
        private void EditDrawn(object o, ToggledArgs args) {
            TreeIter iter;
            CourseListStore.GetIter (out iter, new TreePath (args.Path));
            OrComp.Course course = (OrComp.Course)CourseListStore.GetValue(iter, 0);
            drawCourse = course.Name;
            data.Save(db.data);
        }



        private ListStore CategoryListStore;
        private List<OrComp.Category> categories;
        public VBox Categories(DataBase dataBase)  {
            db = dataBase;
            courses = data.Courses(dataBase.data);
            CourseListStore = new ListStore(typeof(string));
            foreach (OrComp.Course course in courses)
                CourseListStore.AppendValues(course.Name);

            categories = data.Categories(dataBase.data);
            CategoryListStore = new ListStore(typeof(OrComp.Category));
            foreach (OrComp.Category category in categories)
                CategoryListStore.AppendValues(category);

            tree = new TreeView(CategoryListStore);
            tree.EnableGridLines = TreeViewGridLines.Both;
            tree.AppendColumn(
                    Standard.treeColText("Meno",
                        new TreeCellDataFunc(RenderCatName), EditCatName) );
            tree.AppendColumn(
                    Standard.treeColComb("Trať", CourseListStore,
                        new TreeCellDataFunc(RenderCourse), EditCourse) );
            tree.AppendColumn(
                    Standard.treeColText("Prvý štart",
                        new TreeCellDataFunc(RenderFirstTime), EditFirstTime) );
            tree.AppendColumn(
                    Standard.treeColText("Interval",
                        new TreeCellDataFunc(RenderInterval), EditInterval) );

            tree.RulesHint = true;
            Viewport viePo = new Viewport();
            viePo.Add(tree);
            ScrolledWindow viewer = new ScrolledWindow();
            viewer.Add(viePo);

            HBox hbox = new HBox();
            Button button1 = new Button("Pridať kategóriu"),
                   button2 = new Button("Zmazať kategóriu");
            button1.Clicked += AddCategory;
            hbox.Add(button1);
            hbox.Add(button2);

            VBox vbox1 = new VBox();
            vbox1.PackStart(hbox, false, false, 2);
            vbox1.PackStart(viewer, true, true, 2);

            return vbox1;
        }

        private void AddCategory(object o, EventArgs args) {
            CategoryListStore.AppendValues(new OrComp.Category("", courses[0], db.data));
        }

        private void RenderCatName(TreeViewColumn column, CellRenderer cell,
                TreeModel model, TreeIter iter) {
            OrComp.Category category = (OrComp.Category)model.GetValue(iter, 0);
            (cell as CellRendererText).Text = category.Name;
        }
        private void EditCatName(object o, EditedArgs args) {
            TreeIter iter;
            CategoryListStore.GetIter (out iter, new TreePath (args.Path));
            OrComp.Category category = (OrComp.Category)CategoryListStore.GetValue(iter, 0);
            category.Name = args.NewText;
            category.Save(db.data);
        }

        private void RenderFirstTime(TreeViewColumn column, CellRenderer cell,
                TreeModel model, TreeIter iter) {
            OrComp.Category category = (OrComp.Category)model.GetValue(iter, 0);
            (cell as CellRendererText).Text = category.FirstTime.ToString();
        }
        private void EditFirstTime(object o, EditedArgs args) {
            TreeIter iter;
            CategoryListStore.GetIter (out iter, new TreePath (args.Path));
            OrComp.Category category = (OrComp.Category)CategoryListStore.GetValue(iter, 0);
            try {
                category.FirstTime = Standard.String2Int32(args.NewText);
                category.Save(db.data);
            }
            catch {
            }
        }

        private void RenderInterval(TreeViewColumn column, CellRenderer cell,
                TreeModel model, TreeIter iter) {
            OrComp.Category category = (OrComp.Category)model.GetValue(iter, 0);
            (cell as CellRendererText).Text = category.Interval.ToString();
        }
        private void EditInterval(object o, EditedArgs args) {
            TreeIter iter;
            CategoryListStore.GetIter (out iter, new TreePath (args.Path));
            OrComp.Category category = (OrComp.Category)CategoryListStore.GetValue(iter, 0);
            try {
                category.Interval = Standard.String2Int32(args.NewText);
                category.Save(db.data);
            }
            catch {
            }
        }

	private void RenderCourse(TreeViewColumn column, CellRenderer cell,
                TreeModel model, TreeIter iter) {
            OrComp.Category category = (OrComp.Category)model.GetValue(iter, 0);
            (cell as CellRendererCombo).Text = category.Course.Name;
	}
	private void EditCourse(object o, EditedArgs args) {
            TreeIter iter;
            CategoryListStore.GetIter (out iter, new TreePath (args.Path));
            OrComp.Category category = (OrComp.Category)CategoryListStore.GetValue (iter, 0);
            category.Course = data.Course(args.NewText, db.data);
            category.Save(db.data);
	}

    }
}
