using System;
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.Framework.Core;
using VIZ.Package.Domain;
using VIZ.Package.Service;
using VIZ.Package.Storage;

namespace VIZ.Package.Module
{
    /// <summary>
    /// 三元编辑面板模型
    /// </summary>
    public class TripletEditPanelModel : EditPanelModelBase
    {
        public TripletEditPanelModel()
        {
            // 初始化命令
            this.InitCommand();
        }

        /// <summary>
        /// 初始化命令
        /// </summary>
        private void InitCommand()
        {
            this.EditModeChangedCommand = new VCommand<TripletEditPanelMode>(this.EditModeChanged);
        }

        // ============================================================
        // Config
        // ============================================================

        /// <summary>
        /// iz预览编辑器类型: duplet、triplet 数据隐藏过滤器， 使用 "|" 分隔
        /// </summary>
        private readonly static string VIZ_FIELD_EDIT_DUPLET_TRIPLET_HIDDEN_FILTER = ApplicationDomainEx.IniStorage.GetValue<VizConfig, string>(p => p.VIZ_FIELD_EDIT_DUPLET_TRIPLET_HIDDEN_FILTER);

        // ============================================================
        // Field
        // ============================================================

        /// <summary>
        /// 是否正在执行更新值
        /// </summary>
        private bool isInExecuteUpdateValue;

        // ============================================================
        // Property
        // ============================================================

        #region Text -- 文本

        private string text;
        /// <summary>
        /// 文本
        /// </summary>
        public string Text
        {
            get { return text; }
            set
            {
                text = value;
                this.RaisePropertyChanged(nameof(Text));
                this.OnTextChanged();
            }
        }

        #endregion

        #region EditMode -- 编辑模式

        private TripletEditPanelMode editMode = TripletEditPanelMode.Single;
        /// <summary>
        /// 编辑模式
        /// </summary>
        public TripletEditPanelMode EditMode
        {
            get { return editMode; }
            set
            {
                editMode = value;
                this.RaisePropertyChanged(nameof(EditMode));

                if (value == TripletEditPanelMode.Propotional)
                {
                    this.old_x = this.X;
                    this.old_y = this.Y;
                    this.old_z = this.Z;
                }
            }
        }

        #endregion

        #region IsEditModeVisible -- 编辑模式是否可见

        private bool isEditModeVisible = true;
        /// <summary>
        /// 编辑模式是否可见
        /// </summary>
        public bool IsEditModeVisible
        {
            get { return isEditModeVisible; }
            set { isEditModeVisible = value; this.RaisePropertyChanged(nameof(IsEditModeVisible)); }
        }

        #endregion

        #region X -- X值

        /// <summary>
        /// 记录按照百分比改变值时的初始值
        /// </summary>
        private double old_x;

        private double x;
        /// <summary>
        /// X值
        /// </summary>
        public double X
        {
            get { return x; }
            set
            {
                x = value;
                this.RaisePropertyChanged(nameof(X));
                this.UpdateValue(TripletEditPanelValue.X);
            }
        }

        #endregion

        #region Y -- Y值

        /// <summary>
        /// 记录按照百分比改变值时的初始值
        /// </summary>
        private double old_y;

        private double y;
        /// <summary>
        /// Y值
        /// </summary>
        public double Y
        {
            get { return y; }
            set
            {
                y = value;
                this.RaisePropertyChanged(nameof(Y));
                this.UpdateValue(TripletEditPanelValue.Y);
            }
        }

        #endregion

        #region Z -- Z值

        /// <summary>
        /// 记录按照百分比改变值时的初始值
        /// </summary>
        private double old_z;

        private double z;
        /// <summary>
        /// Z值
        /// </summary>
        public double Z
        {
            get { return z; }
            set
            {
                z = value;
                this.RaisePropertyChanged(nameof(Z));
                this.UpdateValue(TripletEditPanelValue.Z);
            }
        }

        #endregion

        // ============================================================
        // Command
        // ============================================================

        #region EditModeChangedCommand -- 编辑模式改变命令

        /// <summary>
        /// 编辑模式改变命令
        /// </summary>
        public VCommand<TripletEditPanelMode> EditModeChangedCommand { get; set; }

        /// <summary>
        /// 编辑模式改变
        /// </summary>
        /// <param name="editMode">编辑模式</param>
        private void EditModeChanged(TripletEditPanelMode editMode)
        {
            this.EditMode = editMode;
        }

        #endregion

        // ============================================================
        // Public Function
        // ============================================================

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="controlObject">控制对象</param>
        /// <param name="controlField">控制字段</param>
        public override void Update(ControlObjectModel controlObject, ControlFieldNodeModel controlField)
        {
            base.Update(controlObject, controlField);

            this.IsSendToPreview = false;
            this.isInExecuteUpdateValue = true;

            this.Text = controlField?.Value;
            this.UpdateValueFromString(this.Text);
            this.UpdateIsEditModeVisible();

            this.isInExecuteUpdateValue = false;
            this.IsSendToPreview = true;
        }

        /// <summary>
        /// 更新动态数据
        /// </summary>
        /// <param name="listCellEdit">列单元格编辑器</param>
        /// <param name="columnDefinition">列定义</param>
        /// <param name="rowHandle">行号</param>
        /// <param name="row">行数据</param>
        public override void UpdateDynamic(ListCellEditBase listCellEdit, GridColumnDefinition columnDefinition, int rowHandle, ExpandoObject row)
        {
            base.UpdateDynamic(listCellEdit, columnDefinition, rowHandle, row);

            IDictionary<string, object> dic = row as IDictionary<string, object>;

            this.IsSendToPreview = false;
            this.isInExecuteUpdateValue = true;

            this.Text = dic?[columnDefinition.FieldName]?.ToString();
            this.UpdateValueFromString(this.Text);
            this.UpdateIsEditModeVisible();

            this.isInExecuteUpdateValue = false;
            this.IsSendToPreview = true;
        }

        /// <summary>
        /// 获取字段值
        /// </summary>
        /// <returns>字段值</returns>
        public override string GetFieldValue()
        {
            return this.Text;
        }

        // ============================================================
        // Private Function
        // ============================================================

        /// <summary>
        /// 文本值改变时触发
        /// </summary>
        private void OnTextChanged()
        {
            // 不需要向预览发送值
            if (!this.IsSendToPreview)
                return;

            // 没有预览连接
            if (ApplicationDomainEx.PreviewConn == null)
                return;

            // 没有控制对象或控制字段
            if (this.ControlObject == null || this.ControlField == null)
                return;

            // 正常模式编辑
            if (this.FieldEditMode == FieldEditMode.Normal)
            {
                this.ControlField.Value = this.Text;

                this.VizCommandControlObjectService.SetControlObjectValue(
                    ApplicationDomainEx.PreviewConn,
                    this.ControlObject.TreeNodePath,
                    this.ControlField.FieldIdentifier,
                    this.ControlField.Value);

                return;
            }

            // 没有列信息或行数据
            if (this.ColumnDefinition == null || this.Row == null)
                return;

            // 动态模式编辑
            if (this.FieldEditMode == FieldEditMode.Dynamic)
            {
                IDictionary<string, object> dic = this.Row as IDictionary<string, object>;
                dic[this.ColumnDefinition.FieldName] = this.Text;

                this.ListCellEdit.UpdateEditValue(this.ColumnDefinition, this.RowHandle, this.Row);

                return;
            }
        }

        /// <summary>
        /// 更新值
        /// </summary>
        /// <param name="value">改变的值</param>
        private void UpdateValue(TripletEditPanelValue value)
        {
            if (this.isInExecuteUpdateValue)
                return;

            this.isInExecuteUpdateValue = true;

            //if (this.EditMode == TripletEditPanelMode.Single)
            //{
            //    // nothing to do
            //}
            if (this.EditMode == TripletEditPanelMode.Locked)
            {
                this.UpdateValue_Locked(value);
            }
            else if (this.EditMode == TripletEditPanelMode.Propotional)
            {
                this.UpdateValue_Propotional(value);
            }

            this.Text = $"{this.X} {this.Y} {this.Z}";

            this.isInExecuteUpdateValue = false;
        }

        /// <summary>
        /// 锁定更新值
        /// </summary>
        /// <param name="value">改变的值</param>
        private void UpdateValue_Locked(TripletEditPanelValue value)
        {
            if (value == TripletEditPanelValue.X)
            {
                this.Y = this.X;
                this.Z = this.X;
            }
            else if (value == TripletEditPanelValue.Y)
            {
                this.X = this.Y;
                this.Z = this.Y;
            }
            else if (value == TripletEditPanelValue.Z)
            {
                this.X = this.Z;
                this.Y = this.Z;
            }
        }

        /// <summary>
        /// 百分比更新值
        /// </summary>
        /// <param name="value">改变的值</param>
        private void UpdateValue_Propotional(TripletEditPanelValue value)
        {
            if (value == TripletEditPanelValue.X)
            {
                this.Y = this.old_x == 0 ? 0 : this.X * (this.old_y / this.old_x);
                this.Z = this.old_x == 0 ? 0 : this.X * (this.old_z / this.old_x);
            }
            else if (value == TripletEditPanelValue.Y)
            {
                this.X = this.old_y == 0 ? 0 : this.Y * (this.old_x / this.old_y);
                this.Z = this.old_y == 0 ? 0 : this.Y * (this.old_z / this.old_y);
            }
            else if (value == TripletEditPanelValue.Z)
            {
                this.X = this.old_z == 0 ? 0 : this.Z * (this.old_x / this.old_z);
                this.Y = this.old_z == 0 ? 0 : this.Z * (this.old_y / this.old_z);
            }
        }

        /// <summary>
        /// 从文本中更新值
        /// </summary>
        /// <param name="text">文本</param>
        private void UpdateValueFromString(string text)
        {
            string[] pars = text?.Split(' ');
            if (pars.Length >= 1)
            {
                double.TryParse(pars[0], out double x);
                this.X = x;
                this.old_x = x;
            }
            if (pars.Length >= 2)
            {
                double.TryParse(pars[1], out double y);
                this.Y = y;
                this.old_y = y;
            }
            if (pars.Length >= 3)
            {
                double.TryParse(pars[2], out double z);
                this.Z = z;
                this.old_z = z;
            }
        }

        /// <summary>
        /// 更新编辑模式是否可见
        /// </summary>
        private void UpdateIsEditModeVisible()
        {
            string[] args = VIZ_FIELD_EDIT_DUPLET_TRIPLET_HIDDEN_FILTER.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
            if (args.Length == 0)
                return;

            string field = this.ControlField.FieldIdentifier ?? string.Empty;
            this.IsEditModeVisible = !args.Any(p => field.Contains(p));
        }
    }
}
