using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms.VisualStyles;
using System.Windows.Input;
using Aitex.Core.RT.Log;
using MECF.Framework.Common.Account;
using MECF.Framework.Common.Account.Extends;
using MECF.Framework.Common.Account.Permissions;
using MECF.Framework.UI.Client.ClientBase;
using OpenSEMI.ClientBase;
using OpenSEMI.ClientBase.Command;

namespace MECF.Framework.UI.Client.CenterViews.Configs.Roles
{
    public class RoleViewModel : BaseModel
    {
        #region Variables

        private bool _isEnabledRoleName;
        private RoleItem _treeSelectedRole;
        private CtrlMode _controlMode = CtrlMode.VIEW;

        #endregion

        #region Constructors

        public RoleViewModel()
        {
            DisplayName = "Role";
        }

        #endregion

        #region Properties

        public bool IsEnabledRoleName
        {
            get => _isEnabledRoleName;
            set
            {
                _isEnabledRoleName = value;
                NotifyOfPropertyChange();
            }
        }

        public ObservableCollection<PermissionMappedType> PermissionDictionary =>
            RolePermissionMapper.Instance.PermissionDictionary;

        public ObservableCollection<PermissionMappedType> PermissionTrueFalseDictionary =>
            RolePermissionTrueFalseMapper.Instance.PermissionDictionary;

        public ObservableCollection<RoleItem> RoleList { get; } = new();

        public RoleItem TreeSelectedRole
        {
            get => _treeSelectedRole;
            set
            {
                _treeSelectedRole = value;
                NotifyOfPropertyChange();
            }
        }

        public CtrlMode ControlMode
        {
            get => _controlMode;
            set
            {
                _controlMode = value;
                NotifyOfPropertyChange();
            }
        }

        #endregion

        #region Methods

        protected override void OnInitialize()
        {
            base.OnInitialize();
            RoleManagerClient.Instance.Initialize();
        }

        protected override void OnActivate()
        {
            RoleList.Clear();
            _treeSelectedRole = null;
            LoadRoleList();

            base.OnActivate();
        }

        protected override void OnDeactivate(bool close)
        {
            if (ControlMode == CtrlMode.EDIT && IsPermission)
            {
                if (DialogBox.Confirm("The data has been modified. Do you want to save the change(s)?"))
                {
                    if (SaveChanges(out var reason))
                    {
                        ControlMode = CtrlMode.VIEW;
                        DialogBox.ShowInfo("Operated successfully.");
                    }
                    else
                    {
                        DialogBox.ShowError($"Operated failed, {reason}");
                    }
                }
            }

            base.OnDeactivate(close);
        }

        public void OnRoleChanged()
        {
            var roleNameList = new[] { "管理员", "设备工程师", "工艺工程师", "操作员" };
            var roleName = roleNameList.Contains(TreeSelectedRole.DisplayRoleName)
                ? TreeSelectedRole.DisplayRoleName
                : "";
            IsEnabledRoleName = true;
            if (!string.IsNullOrEmpty(roleName))
                IsEnabledRoleName = false;

            if (ControlMode == CtrlMode.EDIT)
            {
                if (!string.IsNullOrEmpty(TreeSelectedRole.DisplayRoleName) &&
                    TreeSelectedRole.DisplayRoleName.Length > 18)
                    TreeSelectedRole.DisplayRoleName = TreeSelectedRole.DisplayRoleName.Substring(0, 18);

                return;
            }

            //check role to set the mode from view to edit
            if (_treeSelectedRole != null && _treeSelectedRole.IsRoleChanged())
                ControlMode = CtrlMode.EDIT;
        }

        public bool OnAutoLogoutTimeChecked(object sender)
        {
            ControlMode = CtrlMode.EDIT;
            return ((CheckBox)(sender)).IsChecked.Value;
        }

        private bool SaveChanges(out string reason)
        {
            reason = "";
            if (string.IsNullOrWhiteSpace(TreeSelectedRole.DisplayRoleName))
            {
                reason = "Role Name cannot be empty.";
                return false;
            }

            if (IsRoleExists(TreeSelectedRole))
            {
                reason = "Role already exists.";
                return false;
            }

            TreeSelectedRole.RoleName = TreeSelectedRole.DisplayRoleName;
            TreeSelectedRole.IsAutoLogout = TreeSelectedRole.DisplayIsAutoLogout;
            TreeSelectedRole.AutoLogoutTime = TreeSelectedRole.DisplayAutoLogoutTime;
            TreeSelectedRole.RoleNameTextSaved = TreeSelectedRole.TimeTextSaved = true;
            TreeSelectedRole.Description = TreeSelectedRole.DisplayDescription;

            try
            {
                return RoleManagerClient.Instance.SaveRole(TreeSelectedRole, out reason);
            }
            catch (Exception ex)
            {
                reason = ex.Message;
                LOG.Error(ex.Message, ex);
                return false;
            }
        }

        private bool IsRoleExists(RoleItem role)
        {
            if (RoleList == null || RoleList.Count == 0)
                return false;

            var sameNameList = RoleList.Where(t => t.DisplayRoleName == role.DisplayRoleName);
            if (sameNameList.Count() <= 1)
                return false;

            return true;
        }

        private void LoadRoleList(string defaultSelectedRoleName = "")
        {
            RoleList.Clear();
            var roles = RoleManagerClient.Instance.GetAllRoles();
            if (roles == null || roles.Count == 0)
                return;

            foreach (var ri in roles)
                RoleList.Add(ri);

            if (string.IsNullOrEmpty(defaultSelectedRoleName))
            {
                TreeSelectedRole = RoleList.FirstOrDefault();
                if (TreeSelectedRole != null)
                    TreeSelectedRole.IsSelected = true;
            }
            else
            {
                var roleToSelect = RoleList.FirstOrDefault(x => x.RoleName == defaultSelectedRoleName);
                if (roleToSelect != null)
                    roleToSelect.IsSelected = true;
            }

            ControlMode = CtrlMode.VIEW;
        }

        private void OnRoleTreeSelectedChanged(EventCommandParameter<object, RoutedEventArgs> arg)
        {
            var roleItem = arg.CustomParameter as RoleItem;
            if (roleItem == null)
                return;
            TreeSelectedRole = roleItem;
        }

        private void OnBtnAddRoleCommand(object arg)
        {
            try
            {
                var newRole = RoleManagerClient.Instance.Create();
                if (newRole != null)
                {
                    RoleList.Add(newRole);
                    TreeSelectedRole = newRole;
                    TreeSelectedRole.IsSelected = true;
                }

                ControlMode = CtrlMode.EDIT;
            }
            catch (Exception ex)
            {
                DialogBox.ShowError($"Unable to add role, {ex.Message}");
            }
        }

        private void OnBtnDeleteRoleCommand(object arg)
        {
            if (TreeSelectedRole == null)
                return;

            if (TreeSelectedRole.IsBuildIn)
            {
                DialogBox.ShowError("Can not delete a build-in role");
                return;
            }

            if (!DialogBox.Confirm("Are you sure that you want to delete this role?"))
            {
                return;
            }

            if (BaseApp.Instance.UserContext.Role.RoleId == TreeSelectedRole.RoleId)
            {
                DialogBox.ShowError("The action cannot be completed because {0} is currently in use.", "the role");
                return;
            }


            try
            {
                var index = RoleList.IndexOf(TreeSelectedRole);
                RoleList.Remove(TreeSelectedRole);
                RoleManagerClient.Instance.DeleteRole(TreeSelectedRole.RoleId);
                index = index > 1 ? index - 1 : 0;
                TreeSelectedRole = RoleList?[index];
                if (TreeSelectedRole != null) 
                    TreeSelectedRole.IsSelected = true;
                // DialogBox.ShowInfo("Operated successfully.");
            }
            catch (Exception ex)
            {
                LOG.Error(ex.StackTrace);
                DialogBox.ShowError($"Deleting failed, {ex.Message}");
            }
        }

        private void OnBtnCloneRoleCommand(object arg)
        {
            if (_treeSelectedRole != null)
            {
                var newRole = RoleManagerClient.Instance.Clone(_treeSelectedRole);
                if (newRole != null)
                {
                    newRole.DisplayRoleName = newRole.RoleName = "Copy of " + newRole.DisplayRoleName;
                    RoleList.Add(newRole);
                    TreeSelectedRole = newRole;
                    TreeSelectedRole.IsSelected = true;
                    ControlMode = CtrlMode.EDIT;
                }
            }
        }

        private void OnBtnSaveCommand(object arg)
        {
            try
            {
                if (SaveChanges(out var reason))
                {
                    var lastSelectedRoleName = TreeSelectedRole?.RoleName ?? "";
                    LoadRoleList(lastSelectedRoleName);
                    ControlMode = CtrlMode.VIEW;
                }
                else
                    DialogBox.ShowInfo($"Saving failed, {reason}");
            }
            catch (Exception ex)
            {
                LOG.Error(ex.StackTrace);
                DialogBox.ShowError($"Saving failed, {ex.Message}");
            }
        }

        private void OnBtnCancelRoleCommand(object arg)
        {
            var lastSelectedRoleName = TreeSelectedRole.RoleName;
            LoadRoleList(lastSelectedRoleName);
            ControlMode = CtrlMode.VIEW;
        }

        #endregion

        #region Commands

        private ICommand _roleTreeSelectChangedCmd;

        public ICommand RoleTreeSelectChangedCommand =>
            _roleTreeSelectChangedCmd ??= new BaseCommand<EventCommandParameter<object, RoutedEventArgs>>(
                OnRoleTreeSelectedChanged);

        private ICommand _btnSaveCommand;

        public ICommand BtnSaveCommand => _btnSaveCommand ??= new BaseCommand<object>(OnBtnSaveCommand);

        private ICommand _btnAddRoleCommand;

        public ICommand BtnAddRoleCommand => _btnAddRoleCommand ??= new BaseCommand<object>(OnBtnAddRoleCommand);

        private ICommand _btnDeleteRoleCommand;

        public ICommand BtnDeleteRoleCommand =>
            _btnDeleteRoleCommand ??= new BaseCommand<object>(OnBtnDeleteRoleCommand);

        private ICommand _btnCloneRoleCommand;

        public ICommand BtnCloneRoleCommand => _btnCloneRoleCommand ??= new BaseCommand<object>(OnBtnCloneRoleCommand);

        private ICommand _btnCancelRoleCommand;

        public ICommand BtnCancelRoleCommand =>
            _btnCancelRoleCommand ??= new BaseCommand<object>(OnBtnCancelRoleCommand);

        #endregion

    }
}
