using MainShell.Filewritable;
using MainShell.Models;
using MainShell.Recipe.Models;
using Stylet;
using StyletIoC;
using System;
using System.Collections.ObjectModel;
using System.Linq;

namespace MainShell.Recipe.ViewModel
{
    public class WaferRecipeViewModel : RecipeViewModelBase<WaferRecipe>, IHandle<ProcessNameChangedEventArgs>
    {
        private WaferRecipe _waferRecipe;
        public WaferRecipe WaferRecipe
        {
            get { return _waferRecipe; }
            set
            {
                if (SetAndNotify(ref _waferRecipe, value))
                {
                    if (WaferTeachViewModel != null)
                    {
                        WaferTeachViewModel.WaferRecipe = value;
                    }
                }
            }
        }

        protected override WaferRecipe CurrentRecipe
        {
            get => WaferRecipe;
            set => WaferRecipe = value;
        }

        protected override string RecipeFolderPath => Paths.WaferRecipe;
        protected override string EmptyRecipeDisplayName => "当前芯片配方";

        protected override string GetActiveRecipeName()
        {
            return RecipeManager.CurrentWaferRecipe?.RecipeName;
        }

        private bool _skipProcessSelectionWriteBack;
        private int _selectedTabIndex;

        public int SelectedTabIndex
        {
            get { return _selectedTabIndex; }
            set
            {
                if (SetAndNotify(ref _selectedTabIndex, value))
                {
                    HideRecipePanel = value != 0;
                }
            }
        }

        private WaferTeachViewModel _waferTeachViewModel;
        [Inject]
        public WaferTeachViewModel WaferTeachViewModel
        {
            get { return _waferTeachViewModel; }
            set
            {
                if (SetAndNotify(ref _waferTeachViewModel, value) && value != null)
                {
                    value.WaferRecipe = WaferRecipe;
                }
            }
        }

        private RecipeWrap _selectedProcessRecipeWrap;
        public RecipeWrap SelectedProcessRecipeWrap
        {
            get { return _selectedProcessRecipeWrap; }
            set
            {
                if (SetAndNotify(ref _selectedProcessRecipeWrap, value))
                {
                    if (!_skipProcessSelectionWriteBack && WaferRecipe != null)
                    {
                        WaferRecipe.ProcessRecipeName = value != null ? value.RecipeName : string.Empty;
                        NotifyOfPropertyChange(() => HasUnsavedChanges);
                    }
                }
            }
        }

        public ObservableCollection<RecipeWrap> ProcessRecipes => _wrapManager.ProcessRecipeWraps;

        private readonly RecipeWrapManager _wrapManager;
        private readonly IEventAggregator _eventAggregator;

        public WaferRecipeViewModel(RecipeWrapManager wrapManager, IEventAggregator eventAggregator, RecipeManager recipeManager)
            : base(recipeManager)
        {
            _wrapManager = wrapManager;
            _eventAggregator = eventAggregator;
            RegisterButtonGroupEvents();
            RecipeWraps = wrapManager.WaferRecipeWraps;

            _eventAggregator.Unsubscribe(this);
            _eventAggregator.Subscribe(this);
        }

        protected override void OnViewLoaded()
        {
            base.OnViewLoaded();
            InitializeSelection(RecipeManager.CurrentWaferRecipe?.RecipeName);
            SelectedTabIndex = HideRecipePanel ? 1 : 0;
        }

        protected override void SwitchActiveRecipe(string recipeName)
        {
            RecipeManager.SwitchWaferRecipe(recipeName);
        }

        protected override void ClearActiveRecipe()
        {
            RecipeManager.ClearWaferRecipe();
        }

        protected override void OnRecipeLoaded(WaferRecipe recipe, RecipeWrap recipeWrap)
        {
            SyncProcessSelectionFromWaferRecipe();
        }

        protected override void AfterDeleteCurrentRecipe(string deletedRecipeName)
        {
            _eventAggregator.Publish(new WaferDeletedEventArgs
            {
                DeletedName = deletedRecipeName,
            });
        }

        protected override void AfterRecipeRenamed(string oldRecipeName, string newRecipeName)
        {
            _eventAggregator.Publish(new WaferNameChangedEventArgs
            {
                OldName = oldRecipeName,
                NewName = newRecipeName,
            });

            SyncProcessSelectionFromWaferRecipe();
        }

        public override void OnCopyRecipe(object sender, EventArgs eventArgs)
        {
            base.OnCopyRecipe(sender, eventArgs);
        }

        public override void OnImportRecipe(object sender, EventArgs eventArgs)
        {
            if (eventArgs is RecipeEventArgs args)
            {
            }
        }

        public override void OnExportRecipe(object sender, EventArgs eventArgs)
        {
            if (eventArgs is RecipeEventArgs args)
            {
            }
        }

        public override void OnReNameRecipe(object sender, EventArgs eventArgs)
        {
            if (eventArgs is RecipeRenameEventArgs args)
            {
                TryRenameRecipe(args);
            }
        }

        public void Handle(ProcessNameChangedEventArgs message)
        {
            if (message == null || string.IsNullOrWhiteSpace(message.OldName) || string.IsNullOrWhiteSpace(message.NewName))
                return;

            foreach (RecipeWrap wrap in RecipeWraps)
            {
                WaferRecipe recipe = new WaferRecipe
                {
                    RecipeName = wrap.RecipeName
                };
                recipe.Read();

                if (string.Equals(recipe.ProcessRecipeName, message.OldName, StringComparison.Ordinal))
                {
                    recipe.ProcessRecipeName = message.NewName;
                    recipe.Write();
                }
            }

            if (WaferRecipe != null && string.Equals(WaferRecipe.ProcessRecipeName, message.OldName, StringComparison.Ordinal))
            {
                WaferRecipe.ProcessRecipeName = message.NewName;
                CaptureSavedSnapshot();
            }

            SyncProcessSelectionFromWaferRecipe();
        }

        private void SyncProcessSelectionFromWaferRecipe()
        {
            if (WaferRecipe == null || ProcessRecipes == null)
            {
                SetSelectedProcessRecipeWrapInternal(null);
                return;
            }

            if (string.IsNullOrWhiteSpace(WaferRecipe.ProcessRecipeName))
            {
                SetSelectedProcessRecipeWrapInternal(null);
                return;
            }

            RecipeWrap processWrap = ProcessRecipes.FirstOrDefault(p => p.RecipeName == WaferRecipe.ProcessRecipeName);
            if (processWrap != null)
            {
                SetSelectedProcessRecipeWrapInternal(processWrap);
                return;
            }

            SetSelectedProcessRecipeWrapInternal(null);
        }

        private void SetSelectedProcessRecipeWrapInternal(RecipeWrap recipeWrap)
        {
            try
            {
                _skipProcessSelectionWriteBack = true;
                SelectedProcessRecipeWrap = recipeWrap;
            }
            finally
            {
                _skipProcessSelectionWriteBack = false;
            }
        }

        public void MakeTemplate()
        {
            if (WaferTeachViewModel != null)
            {
                WaferTeachViewModel.MakeTemplate();
            }
        }
    }
}
