using MainShell.Common;
using MainShell.Models;
using MainShell.Recipe.Models;
using MaxwellFramework.Core.Interfaces;
using MwFramework.ManagerService;
using Stylet;
using StyletIoC;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MainShell.Recipe.ViewModel
{
    public class RecipeViewModel :BaseScreen ,IPage
    {
        private bool _isReactivatingAfterBlockedLeave;

        public string Name => "Recipe";
        private const string CARRIER = "载具配方";
        private const string SUBSTRATE = "基板配方";
        private const string WAFER = "芯片配方";
        private const string PROCESS = "工艺配方";
        private readonly Dictionary<string, BaseScreen> _viewModelDict = new Dictionary<string, BaseScreen>();
        public ObservableCollection<MenuItemWrap> MenuItemWraps { get; private set; }
     
        private MenuItemWrap _selectedMenuItem;

        public MenuItemWrap SelectedMenuItem
        {
            get { return _selectedMenuItem; }
            set
            {
                if (_selectedMenuItem == value)
                    return;

                if (_selectedMenuItem != null && value != null && !TryLeaveCurrentScreen())
                {
                    NotifyOfPropertyChange(() => SelectedMenuItem);
                    return;
                }

                if (SetAndNotify(ref _selectedMenuItem, value))
                {
                    CurrentScreen = value != null ? _viewModelDict[value.Header] : null;
                    SyncCurrentScreenSelectionFromActiveRecipe();
                }
            }
        }
        private BaseScreen _currentScreen;

        public BaseScreen CurrentScreen
        {
            get { return _currentScreen; }
            set
            {
                if (_currentScreen == value)
                    return;

                UnsubscribeScreenState(_currentScreen as INotifyPropertyChanged);

                if (SetAndNotify(ref _currentScreen, value))
                {
                    SubscribeScreenState(value as INotifyPropertyChanged);
                    NotifyOfPropertyChange(() => IsRecipePanelHidden);
                }
            }
        }

        public bool IsRecipePanelHidden
        {
            get
            {
                var recipeScreen = CurrentScreen as IRecipeViewModel;
                return recipeScreen != null && recipeScreen.HideRecipePanel;
            }
            set
            {
                var recipeScreen = CurrentScreen as IRecipeViewModel;
                if (recipeScreen == null || recipeScreen.HideRecipePanel == value)
                    return;

                recipeScreen.HideRecipePanel = value;
                NotifyOfPropertyChange(() => IsRecipePanelHidden);
            }
        }

        private CarrierRecipeViewModel _carrierRecipeViewModel;
        [Inject]
        public CarrierRecipeViewModel CarrierRecipeViewModel
        {
            get { return _carrierRecipeViewModel; }
            set { _carrierRecipeViewModel = value; }    
        }
        private SubstrateRecipeViewModel  _substrateRecipeViewModel;
        [Inject]
        public SubstrateRecipeViewModel SubstrateRecipeViewModel
        {
            get { return  _substrateRecipeViewModel; }
            set {  _substrateRecipeViewModel = value; } 
        }
        private WaferRecipeViewModel  _waferRecipeViewModel;
        [Inject]
        public WaferRecipeViewModel  WaferRecipeViewModel
        {
            get { return  _waferRecipeViewModel; }
            set {  _waferRecipeViewModel = value; } 
        }
        private ProcessRecipeViewModel _processRecipeViewModel;
        [Inject]
        public ProcessRecipeViewModel  ProcessRecipeViewModel
        {
            get { return _processRecipeViewModel; }
            set { _processRecipeViewModel = value; } 
        }


        public RecipeViewModel()
        {
            InitMenuItems();
        }

        

        protected override void OnViewLoaded()
        {
            base.OnViewLoaded();
            EnsureViewModelDict();
            if(SelectedMenuItem==null)
                SelectedMenuItem = MenuItemWraps[0];

            SyncCurrentScreenSelectionFromActiveRecipe();
        }
        private void InitMenuItems()
        {
            MenuItemWraps = new ObservableCollection<MenuItemWrap>
            {
                //new MenuItemWrap() { Header=CARRIER,Tag=CARRIER },
                new MenuItemWrap() { Header=SUBSTRATE,Tag=SUBSTRATE },
                new MenuItemWrap() { Header=WAFER,Tag=WAFER },
                new MenuItemWrap() { Header=PROCESS,Tag=PROCESS },
            };
        }
        private void InitViewModelDict()
        {
            _viewModelDict.Clear();
            _viewModelDict.Add(CARRIER, CarrierRecipeViewModel);
            _viewModelDict.Add(SUBSTRATE, SubstrateRecipeViewModel);
            _viewModelDict.Add(WAFER, WaferRecipeViewModel);
            _viewModelDict.Add(PROCESS, ProcessRecipeViewModel);
        }

        private void EnsureViewModelDict()
        {
            if (_viewModelDict.Count == 0)
            {
                InitViewModelDict();
            }
        }

        private void SyncCurrentScreenSelectionFromActiveRecipe()
        {
            var recipeScreen = CurrentScreen as IRecipeViewModel;
            recipeScreen?.SyncSelectionFromActiveRecipe();
        }

        private bool TryLeaveCurrentScreen()
        {
            var guard = CurrentScreen as IRecipeViewModel;
            if (guard == null)
                return true;

            return guard.TryLeaveCurrentRecipeContext();
        }

        public bool TrySelectMenuItem(MenuItemWrap targetMenuItem)
        {
            if (targetMenuItem == null)
                return false;

            SelectedMenuItem = targetMenuItem;
            return SelectedMenuItem == targetMenuItem;
        }

        public bool TrySelectRecipeWrap(RecipeWrap targetRecipeWrap)
        {
            var guard = CurrentScreen as IRecipeViewModel;
            if (guard == null || targetRecipeWrap == null)
                return false;

            if (guard.SelectedRecipeWrap == targetRecipeWrap)
                return true;

            guard.SelectedRecipeWrap = targetRecipeWrap;
            return guard.SelectedRecipeWrap == targetRecipeWrap;
        }

        private void SubscribeScreenState(INotifyPropertyChanged screen)
        {
            if (screen != null)
            {
                screen.PropertyChanged += OnCurrentScreenPropertyChanged;
            }
        }

        private void UnsubscribeScreenState(INotifyPropertyChanged screen)
        {
            if (screen != null)
            {
                screen.PropertyChanged -= OnCurrentScreenPropertyChanged;
            }
        }

        private void OnCurrentScreenPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(e.PropertyName) || string.Equals(e.PropertyName, nameof(BaseScreen.HideRecipePanel), StringComparison.Ordinal))
            {
                NotifyOfPropertyChange(() => IsRecipePanelHidden);
            }
        }

        protected override void OnStateChanged(ScreenState previousState, ScreenState newState)
        {
            base.OnStateChanged(previousState, newState);

            if (_isReactivatingAfterBlockedLeave)
                return;

            if (newState == ScreenState.Active)
            {
                EnsureViewModelDict();
                if (SelectedMenuItem == null && MenuItemWraps != null && MenuItemWraps.Count > 0)
                {
                    SelectedMenuItem = MenuItemWraps[0];
                }

                SyncCurrentScreenSelectionFromActiveRecipe();
            }

            if (previousState == ScreenState.Active && newState == ScreenState.Deactivated && !TryLeaveCurrentScreen())
            {
                try
                {
                    _isReactivatingAfterBlockedLeave = true;
                    Execute.OnUIThread(() => ((IScreenState)this).Activate());
                }
                finally
                {
                    _isReactivatingAfterBlockedLeave = false;
                }
            }
        }

        protected override void OnDeactivate()
        {
            UnsubscribeScreenState(_currentScreen as INotifyPropertyChanged);
            base.OnDeactivate();
        }

    }
}
