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.Text;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Xml;
using Machinations.Annotations;
using Machinations.UserComponents;

namespace Machinations.WPF
{
    /// <summary>
    /// Interaction logic for UserComponentControlView.xaml
    /// </summary>
    public partial class UserComponentControlView : INotifyPropertyChanged
    {
        //private List<IUserComponentSchema> m_components;
        private readonly ObservableCollection<UserComponent> m_userComponents;
        private readonly ObservableCollection<Cards> m_cards;
        private ObservableCollection<Cards> m_createdCards; 
        private ToggleButton m_checkedButton;
        private IUserComponentSchema m_selectedComponent;
        
        public Action ButtonChecked;
        private bool m_cardsAllowed = true;

        public UserComponentControlView()
        {
            m_userComponents = new ObservableCollection<UserComponent>();
            m_cards = new ObservableCollection<Cards>();
            m_createdCards = new ObservableCollection<Cards>();
            //ReloadComponents();         xaml editor ve VS pak neumi nacist
            InitializeComponent();
        }

        public ObservableCollection<UserComponent> UserComponents
        {
            get
            {
                return m_userComponents;
            }
        }

        public ObservableCollection<Cards> Cards
        {
            get
            {
                return m_cards;
            }
        }

        public bool HasCreatedCards
        {
            get { return CreatedCards.Count > 0; }
        }

        public ObservableCollection<Cards> CreatedCards
        {
            get { return m_createdCards; }
        }

        public IUserComponentSchema SelectedComponent
        {
            get { return m_selectedComponent; }
        }

        public bool CardsAllowed
        {
            get { return m_cardsAllowed; }
            internal set {
                if (m_cardsAllowed != value)
                {
                    m_cardsAllowed = value;
                    OnPropertyChanged(nameof(CardsAllowed));
                }
            }
        }

        public void ReloadComponents()
        {
            m_userComponents.Clear();
            m_cards.Clear();
            Directory.CreateDirectory(MachinationsVariables.ComponentsDirectory);               //pokud je vytvorene, nevytvori se znovu
            string[] names = Directory.GetFiles(MachinationsVariables.ComponentsDirectory);
            StringBuilder badNames = new StringBuilder();
            foreach (string name in names)
            {
                try
                {
                    if (m_cards.All(uc => uc.Name != name ) && m_userComponents.All(uc => uc.Name != name))
                    {
                        XmlDocument document = new XmlDocument();
                        document.Load(name);
                        XmlElement element = document.DocumentElement;
                        if (element.Name.Equals(MachinationsVariables.ComponentTemplate))
                            m_userComponents.Add(new UserComponent(name));
                        else if (element.Name.Equals(MachinationsVariables.CardsTemplate))
                            m_cards.Add(new Cards(name));
                        else throw new ArgumentException();
                    }
                }
                catch(Exception)
                {
                    badNames.AppendLine(name);
                }
            }
            if(badNames.Length > 0)
                MessageBox.Show("Unable to load components: " + Environment.NewLine + badNames);
        }

        public void AcceptComponents(IEnumerable<IUserComponentSchema> existingComponents, bool cardsAllowed = false)
        {
            foreach (var schema in existingComponents)
            {
                if (schema is UserComponent)
                {
                    m_userComponents.Add((UserComponent)schema);
                }else if (schema is Cards)
                {
                    m_cards.Add((Cards)schema);
                }
                else
                {
                    throw new ArgumentException();
                }
            }
            CardsAllowed = cardsAllowed;
        }

        public void CreatedCardsChanged(List<IUserComponentSchema> createdComponents)
        {
            if(CreatedCards.SequenceEqual(createdComponents.Where(cc => cc.Type == UserComponentType.Card)))
                return;
            CreatedCards.Clear();
            foreach (var card in createdComponents.Where(uc => uc.Type == UserComponentType.Card))
            {
                CreatedCards.Add((Cards)card);
            }
            OnPropertyChanged(nameof(CreatedCards));
            OnPropertyChanged(nameof(HasCreatedCards));
        }

        //public void Refresh()
        //{
        //    OnPropertyChanged("UcButtonsControl");
        //}

        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            ToggleButton button = sender as ToggleButton;
            if (button?.IsChecked == true)
            {
                UncheckButton();
                m_checkedButton = button;
                if (button.DataContext is IUserComponentSchema)
                    m_selectedComponent = (IUserComponentSchema) button.DataContext;
                else
                {
                    switch ((string)button.Tag)
                    {
                        case "UserComponent":
                            m_selectedComponent = new UserComponent { Name = MachinationsVariables.UserComponentInitName };
                            break;
                        case "Card": 
                            m_selectedComponent = new Cards() {Name = MachinationsVariables.CardsInitName };
                            break;
                        default:throw new ArgumentException();
                    }
                }
                ButtonChecked?.Invoke();
            }
            else m_checkedButton = null;
        }

        public void UncheckButton()
        {
            if (m_checkedButton != null)
            {
                m_checkedButton.IsChecked = false;
                OnPropertyChanged(m_checkedButton.Name);
                m_checkedButton = null;
                m_selectedComponent = null;
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

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

        public void TryAddComponents(IEnumerable<IUserComponentSchema> ucs)
        {
            foreach (var uc in ucs)
            {
                var internalComponents = uc.GetInnerComponents();
                TryAddComponents(internalComponents);
                if (uc.Type == UserComponentType.UserComponent)
                {
                    if (!m_userComponents.Any(c => c.SameSchema(uc)))
                    {
                        m_userComponents.Add((UserComponent)uc);
                        uc.SaveToComponentsFolder();
                    }
                }
                else if (uc.Type == UserComponentType.Card)
                {
                    if (!m_cards.Any(c => c.SameSchema(uc)))
                    {
                        m_cards.Add((Cards)uc);
                        uc.SaveToComponentsFolder();
                    }
                }
            }
        }
    }
}
