using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
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.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 bool WithPlayers
        {
            get { return m_graph?.WithPlayers ?? false ; }
            set { m_graph.WithPlayers = value; }
        }

        public ObservableCollection<IPlayer> Players
        {
            get { return m_graph?.Players; }
        }


        public void Initialize(MachinationsGraph graph, PaintingCanvas paintingCanvas)
        {
            m_graph = graph;
            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);
            m_graph.PlayerChanged += () =>
            {
                OnPropertyChanged(nameof(Players));
                OnPropertyChanged(nameof(WithPlayers));
            };

        }

        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((MachinationsGrammar)m_graph.Grammar);
        }

        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");
                }
            }
        }
<<<<<<< working copy


        private void DeletePlayer(object sender, RoutedEventArgs e)
        {
            var player = Players.First(p => p.Name.Equals(((Button) sender).Tag.ToString()));
            Players.Remove(player);
            player.Dispose();
            OnPropertyChanged(nameof(Players));
        }


        private void AddPlayer(object sender, RoutedEventArgs e)
        {
            var availColors = new List<Color>() {Colors.Red, Colors.Blue, Colors.Yellow, Colors.Green, Colors.Brown, Colors.Pink, Colors.DeepPink};
            Players.ToList().ForEach(p => availColors.Remove(p.Color));
            Players.Add(new PlayerBase("Player" + Players.Count, availColors.Any() ? availColors.First(): Colors.DeepPink));
            OnPropertyChanged(nameof(Players));
        }
=======
>>>>>>> merge rev
    }
}
