using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Media;
using System.Windows.Threading;
using System.Xml;
using Machinations.Annotations;
using Machinations.FromFlash.machinations.model;
using Machinations.Log;
using Machinations.Status;
using Machinations.UserComponents;
using Machinations.WPF;
using MessageBox = System.Windows.MessageBox;
using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
using SaveFileDialog = Microsoft.Win32.SaveFileDialog;

namespace Machinations
{
    /// <summary>
    /// Interaction logic for ProgramControl.xaml
    /// </summary>
    public partial class ProgramControl : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private MachnationsSettings m_settings;
        private PaintingCanvas m_paintingCanvas;
        private MachinationsGraph m_graph;
        private bool m_timerTicking;


        public ProgramControl()
        {
            InitializeComponent();
            UserComponents.ReloadComponents();
            UserComponents.ButtonChecked += UserComponentChosen;
            GraphControl.ButtonPressed += GraphControlButtonPressed;

            MySimulationControl.Timer.Interval = new TimeSpan(0, 0, 1);
        }

        public DispatcherTimer Timer
        {
            get { return MySimulationControl.Timer; }
        }

        public bool TimerTicking
        {
            get { return m_timerTicking; }
            set { m_timerTicking = value; }
        }


        public MachnationsSettings Settings
        {
            get
            {
                if (m_settings == null) m_settings = new MachnationsSettings();
                return m_settings;
            }
        }

        public bool Running
        {
            get
            {
                if (m_graph == null) return false;
                return m_graph.Running;
            }
            set
            {
                m_graph.Running = value;
                OnPropertyChanged(nameof(Running));
            }
        }


        public void Initialize(MachinationsGraph graph, PaintingCanvas paintingCanvas)
        {
            m_graph = graph;
            m_graph.Log = new SimulationLog();
            MySimulationControl.Initialize(m_graph, paintingCanvas);
            paintingCanvas.ComponentsChanged += UserComponents.ReloadComponents;
            paintingCanvas.ComponentsChanged += () => AddSchemasToGraph(paintingCanvas);
            //MachinationsVariables.ComponentDirectoryChanged += () =>
            //{
            //    UserComponents.ReloadComponents();
            //    AddSchemasToGraph(paintingCanvas);
            //};
            AddSchemasToGraph(paintingCanvas);
            paintingCanvas.CreatedCardsChanged += CreatedCardsChanged;
            //OnPropertyChanged(nameof(Running));
            m_paintingCanvas = paintingCanvas;
            ComponentsSettings.Initialize(graph, paintingCanvas);
            GraphControl.SelectAllPressed += paintingCanvas.SelectAll;
        }

        private List<IUserComponentSchema> AddSchemasToGraph(PaintingCanvas paintingCanvas)
        {
            return paintingCanvas.Schemas =
                ((IEnumerable<IUserComponentSchema>) UserComponents.UserComponents).Concat(UserComponents.Cards)
                    .ToList();
        }

        private void CreatedCardsChanged()
        {
            UserComponents.CreatedCardsChanged(m_graph.UserComponents);
        }

        private void Restart_OnClick(object sender, RoutedEventArgs e)
        {
            Reset();
        }

        public void Reset()
        {
            m_graph.Clear();
            m_paintingCanvas.Reset();
        }


        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private void RunButtonClick(object sender, RoutedEventArgs e)
        {
            if (!Running)
            {
                if (m_settings.AutoSave)
                {
                    SaveGraph(MachnationsSettings.LastGraph);
                }
                m_paintingCanvas.UnselectObjects();
                RunButton.Content = "Stop";
                RunButton.Background = Brushes.Red;
                m_graph.DoEvents = true;
                MySimulationControl.Start();
                Running = true;
                MySimulationControl.StatusHandler.CreateFirstRecord();
                m_timerTicking = true;

            }
            else
            {
                RunButton.Content = "Start";
                RunButton.Background = Brushes.LightGreen;
                MySimulationControl.Stop();
                m_timerTicking = false;
                Running = false;
            }
        }

        private void SaveButtonClick(object sender, RoutedEventArgs e)
        {
            SaveFileDialog dialog = new SaveFileDialog();
            dialog.FileName = ("Diagram " + DateTime.Now).Replace(':', '.');
            dialog.Filter = "Xml documents (.xml)|*.xml";
            var result = dialog.ShowDialog();
            if (result == true)
            {
                string fileName = dialog.FileName;
                SaveGraph(fileName);
            }
        }

        private void SaveGraph(string fileName)
        {
            
            XmlDocument document = m_graph.GenerateXml();
            document.Save(fileName);
        }

        private void OpenButtonClick(object sender, RoutedEventArgs e)
        {
            AddData(true);
        }

        private void ImportButtonClick(object sender, RoutedEventArgs e)
        {
            AddData(false);
        }

        private void UserComponentChosen()
        {
            GraphControl.GraphButtonUncheck();
            m_paintingCanvas.InsertedObject = UserComponents.SelectedComponent;
        }

        private void GraphControlButtonPressed()
        {
            UserComponents.UncheckButton();
            m_paintingCanvas.InsertedObject = GraphControl.CreateElement();
        }

        private void AddData(bool overwrite)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = "Xml documents (.xml)|*.xml";
            var result = dialog.ShowDialog();
            if (result == true)
            {
                ProgramControlUtils.OpenFile(overwrite, dialog.FileName, m_graph, this, m_paintingCanvas);
            }
        }


        private void ChangeComponentFolder(object sender, RoutedEventArgs e)
        {
            using (FolderBrowserDialog dialog = new FolderBrowserDialog() {SelectedPath = Path.GetFullPath(Settings.ComponentPath)})
            {
                var result = dialog.ShowDialog();
                if (result == DialogResult.OK)
                {
                    Settings.SaveComponentPath(dialog.SelectedPath);
                    MessageBox.Show("Změna se projeví až po restartu programu");
                }
            }
        }
    }
}
