using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XmdsCommon.Plugin;
using CommonLang.Log;
using XmdsCommon.EditorData;
using CommonAI.Zone.Helper;
using XmdsCommonServer.Plugin.XmdsSkillTemplate.DamageCalculator;
using CommonAI.Data;

namespace XmdsServerEdgeJS
{
    public class XmdsPlayerUtil
    {
		public class UnitSkillData
		{
			public XmdsUnitSkillInfo normalSkill = new XmdsUnitSkillInfo();
			public XmdsUnitSkillInfo cardSkill = new XmdsUnitSkillInfo();
		}

        private readonly Logger log = LoggerFactory.GetLogger("XmdsPlayer");
        private static XmdsPlayerUtil _instance;

        /// 单件实例
        public static XmdsPlayerUtil instance()
        {
            if (_instance == null)
            {
                _instance = new XmdsPlayerUtil();
            }
            return _instance;
        }

        public static void instance(XmdsPlayerUtil value)
        {
            _instance = value;
        }

        public XmdsUnitData createXmdsUnitData(dynamic input, string playerId)
        {
            try
            {
                XmdsUnitData data = new XmdsUnitData();
                data.BaseInfo = createXmdsUnitBaseInfo(input.basic);
                data.UnitPKInfo = createXmdsPKInfo(input.pkInfo);
                data.AvatarList = createXmdsAvatarInfoList(input.avatars);
                data.Prop = createXmdsUnitProp(input.effects, playerId);
                data.Prop.HP = (int)input.tempData.hp;
				if(data.Prop.HP <= 0)
				{
					log.Error("单位血量为负值:" + data.Prop.HP);
					//防止异常
					data.Prop.HP = 1;
				}
                data.PropExt = createXmdsUnitProp(input.effectsExt, playerId);

				UnitSkillData skillData = createXmdsUnitSkillInfo(input.skills);
				data.Skills = skillData.normalSkill;
				data.CardSkills = skillData.cardSkill;
				int addTestPetData = (int)input.addTestPetData;
                if (addTestPetData == 1)
                {
                    data.UnitPetData = createPetData(input.petBase, input.petEffect, input.petSkill, input.petMode);
                }
                data.UnitSceneInfo = createSceneInfo(input.sceneData);
                return data;
            }
            catch (Exception err)
            {
                log.Error("createXmdsUnitData error: " + err.Message, err);
                return null;
            }
        }

        public SceneInfo createSceneInfo(dynamic sceneData)
        {
            try
            {
                int allowAutoGuard = (int)sceneData.allowAutoGuard;
                SceneInfo sceneInfo = new SceneInfo();
                sceneInfo.AllowAutoGuard = true;
                if (allowAutoGuard == 1)
                {
                    sceneInfo.AllowAutoGuard = false;
                }

                return sceneInfo;
            }
            catch (Exception err)
            {
                log.Error("createPetConfig error: " + err.Message, err);
                return null;
            }
        }

        public PetData createPetData(dynamic petBase, dynamic petEffect, dynamic petSkill, dynamic petMode)
        {
            try
            {
                PetData petData = new PetData();
                PetBaseInfo baseInfo = createPetBaseData(petBase);
                petData.BaseInfo = baseInfo;
                XmdsUnitProp unitProp = createXmdsUnitProp(petEffect, "");
                petData.UnitProp = unitProp;
				UnitSkillData skillData = createXmdsUnitSkillInfo(petSkill);
				XmdsUnitSkillInfo skillInfo = skillData.normalSkill;
                petData.SkillInfo = skillInfo;
                XmdsPetConifg petConfigInfo = createPetConfig(petMode);
                petData.PetConfig = petConfigInfo;
                return petData;
            }
            catch (Exception err)
            {
                log.Error("createPetData error: " + err.Message, err);
                return null;
            }
        }

        public XmdsPetConifg createPetConfig(dynamic petMode)
        {
            try
            {
                XmdsPetConifg petConfigInfo = new XmdsPetConifg();
                petConfigInfo.Mode = (XmdsPetConifg.XmdsPetFollowMode)petMode;

                return petConfigInfo;
            }
            catch (Exception err)
            {
                log.Error("createPetConfig error: " + err.Message, err);
                return null;
            }
        }

        public PetBaseInfo createPetBaseData(dynamic petBase)
        {
            try
            {
                PetBaseInfo baseInfo = new PetBaseInfo();
                baseInfo.AvatarModel = (string)petBase.Model;
                baseInfo.AvatarModelScale = (int)petBase.ModelPercent;
                baseInfo.EffectModel = (string)petBase.ModelStar;
                baseInfo.EffectScale = (int)petBase.ModelStarPercent;
                baseInfo.EffectSceneScale = (int)petBase.ModelStarScenePercent;
                baseInfo.level = (int)petBase.level;
                baseInfo.name = (string)petBase.name;
                baseInfo.QColor = (byte)petBase.Qcolor;
                baseInfo.TemplateID = (int)petBase.templateId;
                baseInfo.IconName = (string)petBase.Icon;
                baseInfo.StateLv = (byte)petBase.upGradeLevel;

                return baseInfo;
            }
            catch (Exception err)
            {
                log.Error("createPetBaseData error: " + err.Message, err);
                return null;
            }
        }

        public PKInfo createXmdsPKInfo(dynamic input)
        {
            try
            {
                PKInfo pkInfo = new PKInfo();
                pkInfo.CurPKMode = (PKMode)input.mode;
                pkInfo.CurPKValue = (int)input.value;
                pkInfo.CurPKLevel = (PKLevel)input.level;
                return pkInfo;
            }
            catch (Exception err)
            {
                log.Error("createXmdsPKInfo error: " + err.Message, err);
                return null;
            }
        }

        public XmdsUnitBaseInfo createXmdsUnitBaseInfo(dynamic input)
        {
            XmdsUnitBaseInfo baseInfo = new XmdsUnitBaseInfo();
            baseInfo.name = (string)input.name;
            baseInfo.force = input.force;
            baseInfo.alliesForce = input.alliesForce;
            baseInfo.GuildID = (string)input.guildId;
            baseInfo.GuildName = (string)input.guildName;
            baseInfo.ProType = (CommonAI.Data.XmdsUnitPro)input.pro;
            baseInfo.ServerID = (int)input.serverId;
            baseInfo.TitleID = (int)input.titleId;
            baseInfo.UnitLv = (int)input.level;
            baseInfo.VIPLv = (int)input.vip;
            baseInfo.StateLv = (byte)input.upLevel;
            int beReward = (int)input.beReward;
            baseInfo.SPState = (CommonAI.XmdsConstConfig.SpecialState)beReward;
            baseInfo.logicServerId = (int)input.logicServerId;
            baseInfo.sex = (byte)input.sex;
            baseInfo.uuid = input.uuid;
            baseInfo.potionAddition = ((float)input.potionAddition) / 10000;
			return baseInfo;
        }

        public List<XmdsAvatarInfo> createXmdsAvatarInfoList(dynamic input)
        {
            try
            {
                List<XmdsAvatarInfo> prop = new List<XmdsAvatarInfo>();
                foreach (dynamic obj in input)
                {
                    XmdsAvatarInfo avatar = new XmdsAvatarInfo();
                    avatar.PartTag = (XmdsAvatarInfo.XmdsAvatar)obj.tag;
                    avatar.FileName = (string)obj.fileName;
                    avatar.EffectType = (byte)obj.effectType;
                    prop.Add(avatar);
                }
                return prop;
            }
            catch (Exception err)
            {
                log.Error("createXmdsAvatarInfoList error: " + err.Message, err);
                return null;
            }
        }

        /*注意,该接口为玩家和宠物公用,单方新增字段需加判断,否则会报错(如下:bagRemainCount和teamBagRemainCount字段)*/
        public XmdsUnitProp createXmdsUnitProp(dynamic input, string playerId)
        {
            try
            {
                XmdsUnitProp prop = new XmdsUnitProp();
                //生命
                prop.BaseMaxHP = (input.MaxHP != null) ? (int)input.MaxHP : 0;
                prop.HPPer = (input.HPPer != null) ? (int)input.HPPer : 0;
                prop.HP = (input.HP != null) ? (int)input.HP : prop.BaseMaxHP;

                //攻击
                prop.BaseAttack = (input.Attack != null) ? (int)input.Attack : 0;
                prop.AttackPer = (input.AttackPer != null) ? (int)input.AttackPer : 0;

                //防御
                prop.BaseDefence = (input.Def != null) ? (int)input.Def : 0;
                prop.DefencePer = (input.DefPer != null) ? (int)input.DefPer : 0;

                //无视防御
                prop.BaseIgnoreDefense = (input.IgnoreDefense != null) ? (int)input.IgnoreDefense : 0;
                prop.IgnoreDefensePer = (input.IgnoreDefensePer != null) ? (int)input.IgnoreDefensePer : 0;

                //暴击
                prop.CritRate = (input.CritRate != null) ? (int)input.CritRate : 0;                
                prop.BaseResCrit = (input.Rescrit != null) ? (int)input.Rescrit : 0;
                prop.ResCritPer = (input.ResCritPer != null) ? (int)input.ResCritPer : 0;
                prop.ResCritRate = (input.ResCritRate != null) ? (int)input.ResCritRate : 0;
                prop.CritDamage = (input.CritDamage != null) ? (int)input.CritDamage : 0;
                prop.CritDamageRes = (input.CritDamageRes != null) ? (int)input.CritDamageRes : 0;

                //伤害整体
                prop.PlayerDamageAdd = (input.IncAllDamage != null) ? (int)input.IncAllDamage : 0;
                prop.PlayerDamageReduce = (input.AllDamageReduce != null) ? (int)input.AllDamageReduce : 0;
                prop.CtrlTimeReduce = (input.CtrlTimeReduce != null) ? (int)input.CtrlTimeReduce : 0;
                prop.SkillCD = (input.SkillCD != null) ? (int)input.SkillCD : 0;
                prop.HPReborn = (input.HPRegen != null) ? (int)input.HPRegen : 0;
				prop.HPRecoverPer = (input.HPRecoverPer != null) ? (int)input.HPRecoverPer : 0;
				prop.HealEffect = (input.HealEffect != null) ? (int)input.HealEffect : 0;
                prop.HealedEffect = (input.HealedEffect != null) ? (int)input.HealedEffect : 0;
                prop.MoveSpeed = (input.MoveSpeed != null) ? (float)input.MoveSpeed : 0;
				if (prop.MoveSpeed != 0 && (prop.MoveSpeed > 100 || prop.MoveSpeed < 2))
				{
					log.Warn("玩家/宠物移速确定是认真的? : " + prop.MoveSpeed + ", " + playerId);
				}

				prop.VelocityAddition = (input.RunSpeed != null) ? (int)input.RunSpeed : 0;
                prop.CurInventorySize = (input.bagRemainCount != null) ? (int)input.bagRemainCount : 0;
                prop.CurTeamInventorySize = (input.teamBagRemainCount != null) ? (int)input.teamBagRemainCount : 0;

                //2019.7.10新增属性
                prop.SkillDamageAdd = (input.SkillDamage != null) ? (int)input.SkillDamage : 0;
                prop.AttackSpeed = (input.AttackSpeed != null) ? (int)input.AttackSpeed : 0;
                prop.ControlUp = (input.ControlUp != null) ? (int)input.ControlUp : 0;
				if(prop.AttackSpeed != 0 && (prop.AttackSpeed > 100000 || prop.AttackSpeed < 1000))
				{
					log.Warn("玩家/宠物攻速确定是认真的? : " + prop.AttackSpeed);
					//prop.AttackSpeed = 10000;
				}

                //元素攻击 & 防御
                prop.ArtifactAttack[(int)ArtifactType.Gold] = (input.GoldAttack != null) ? (int)input.GoldAttack : 0;
                prop.ArtifactAttack[(int)ArtifactType.Wood] = (input.WoodAttack != null) ? (int)input.WoodAttack : 0;
                prop.ArtifactAttack[(int)ArtifactType.Water] = (input.WaterAttack != null) ? (int)input.WaterAttack : 0;
                prop.ArtifactAttack[(int)ArtifactType.Fire] = (input.FireAttack != null) ? (int)input.FireAttack : 0;
                prop.ArtifactAttack[(int)ArtifactType.Soil] = (input.SoilAttack != null) ? (int)input.SoilAttack : 0;

                prop.ArtifactDefense[(int)ArtifactType.Gold] = (input.GoldDefense != null) ? (int)input.GoldDefense : 0;                
                prop.ArtifactDefense[(int)ArtifactType.Wood] = (input.WoodDefense != null) ? (int)input.WoodDefense : 0;               
                prop.ArtifactDefense[(int)ArtifactType.Water] = (input.WaterDefense != null) ? (int)input.WaterDefense : 0;               
                prop.ArtifactDefense[(int)ArtifactType.Fire] = (input.FireDefense != null) ? (int)input.FireDefense : 0;              
                prop.ArtifactDefense[(int)ArtifactType.Soil] = (input.SoilDefense != null) ? (int)input.SoilDefense : 0;

                //元素克制 & 抵御
                prop.ArtifactRestraint[(int)ArtifactType.Gold] = (input.GoldRestraint != null) ? (int)input.GoldRestraint : 0;
                prop.ArtifactRestraint[(int)ArtifactType.Wood] = (input.WoodRestraint != null) ? (int)input.WoodRestraint : 0;
                prop.ArtifactRestraint[(int)ArtifactType.Water] = (input.WaterRestraint != null) ? (int)input.WaterRestraint : 0;
                prop.ArtifactRestraint[(int)ArtifactType.Fire] = (input.FireRestraint != null) ? (int)input.FireRestraint : 0;
                prop.ArtifactRestraint[(int)ArtifactType.Soil] = (input.SioilRestraint != null) ? (int)input.SoilRestraint : 0;

                prop.ArtifactResist[(int)ArtifactType.Gold] = (input.GoldResist != null) ? (int)input.GoldResist : 0;
                prop.ArtifactResist[(int)ArtifactType.Wood] = (input.WoodResist != null) ? (int)input.WoodResist : 0;
                prop.ArtifactResist[(int)ArtifactType.Water] = (input.WaterResist != null) ? (int)input.WaterResist : 0;
                prop.ArtifactResist[(int)ArtifactType.Fire] = (input.FireResist != null) ? (int)input.FireResist : 0;
                prop.ArtifactResist[(int)ArtifactType.Soil] = (input.SoilResist != null) ? (int)input.SoilResist : 0;

                //元素主属性加成
                prop.ArtifactMainPer = (input.ArtifactMainPer != null) ? input.ArtifactMainPer : 0;

                //boss伤害
                prop.ToBossCritRate = (input.ToBossCritRate != null) ? (int)input.ToBossCritRate : 0;
                prop.ToBossCritDamage = (input.ToBossCritDamage != null) ? (int)input.ToBossCritDamage : 0;
                
                prop.KillValuePer = (input.PvpKillValue != null) ? (int)input.PvpKillValue : 0;
                prop.YaoQiLevel = (input.YaoQiLevel != null) ? (int)input.YaoQiLevel : 0;

                //吸血
                prop.NormalAtkLeech = (input.NormalAtkLeech != null) ? (int)input.NormalAtkLeech : 0;
                prop.ActiveAtkLeech = (input.ActiveAtkLeech != null) ? (int)input.ActiveAtkLeech : 0;

                //怪物增伤
                prop.monsterDamageAdd = (input.FieldBossDamageAdd != null) ? (int)input.FieldBossDamageAdd : 0;
                prop.monsterDamageReduce = (input.DungeonMonsterDamageAdd != null) ? (int)input.DungeonMonsterDamageAdd : 0;

				//人物命格伤害加成
				prop.MonsterRestraint[0] = (input.MonsterRestraint1 != null) ? (int)input.MonsterRestraint1 : 0;
				prop.MonsterRestraint[1] = (input.MonsterRestraint2 != null) ? (int)input.MonsterRestraint2 : 0;
				prop.MonsterRestraint[2] = (input.MonsterRestraint3 != null) ? (int)input.MonsterRestraint3 : 0;
				prop.MonsterRestraint[3] = (input.MonsterRestraint4 != null) ? (int)input.MonsterRestraint4 : 0;
				prop.MonsterRestraint[4] = (input.MonsterRestraint5 != null) ? (int)input.MonsterRestraint5 : 0;

				//宠物天命属性
				prop.fateType = (input.fateType != null) ? (UnitFateType)input.fateType : UnitFateType.None;
				prop.fateValue = (input.fateValue != null) ? (int)input.fateValue : 0;

				//神器,背饰
				//神器属性
				prop.ArtifactIndex = (input.artifactIndex != null) ? input.artifactIndex : (int)ArtifactType.None;
				if (prop.ArtifactIndex < (int)ArtifactType.None || prop.ArtifactIndex > (int)ArtifactType.Fire)
				{
					prop.ArtifactIndex = (int)ArtifactType.None;
				}

				//神器背饰id
				prop.ArtifactDefenceIndex = (input.artifactDefenceIndex != null) ? input.artifactDefenceIndex : (int)ArtifactType.None;
				if (prop.ArtifactDefenceIndex < (int)ArtifactType.None || prop.ArtifactDefenceIndex > (int)ArtifactType.Fire)
				{
					prop.ArtifactDefenceIndex = (int)ArtifactType.None;
				}

				prop.BreakShieldValue = (input.breakShieldValue != null) ? input.breakShieldValue : 0;

				//猎妖属性
				prop.monsterAtk = (input.MonsterAtk != null) ? (int)input.MonsterAtk : 0;
				prop.monsterDef = (input.MonsterDef != null) ? (int)input.MonsterDef : 0;
				prop.monsterAtkPer = (input.MonsterAtkPer != null) ? (int)input.MonsterAtkPer : 0;
				prop.monsterDefPer = (input.MonsterDefPer != null) ? (int)input.MonsterDefPer : 0;

				return prop;
            }
            catch (Exception err)
            {
                log.Error("createXmdsUnitProp error: " + err.Message, err);
                return null;
            }
        }

        public UnitSkillData createXmdsUnitSkillInfo(dynamic input)
        {
            try
            {
				UnitSkillData unitSkillData = new UnitSkillData();
				unitSkillData.normalSkill.UnitSkills = new List<GameSkill>();
				unitSkillData.cardSkill.UnitSkills = new List<GameSkill>();

                foreach (dynamic obj in input)
                {
                    GameSkill skill = new GameSkill();
                    skill.SkillTimestampMS = (long)obj.skillTime;
                    skill.SkillID = (int)obj.id;
                    skill.SkillLevel = (int)obj.level;
                    skill.SkillType = (XmdsSkillType)obj.type;
                    if(obj.talentLevel != null)
                    {
                        skill.TalentSkillLevel1 = (int)obj.talentLevel[0];
                        skill.TalentSkillLevel2 = (int)obj.talentLevel[1];
                        skill.TalentSkillLevel3 = (int)obj.talentLevel[2];
                    }
                  
                    if (obj.cdTime != null)
                    {
                        skill.SkillCDDecreasePercent = (int)obj.cdTime;
                    }

					if(skill.SkillType == XmdsSkillType.cardSkill)
					{
						unitSkillData.cardSkill.UnitSkills.Add(skill);
					}
					else
					{
						unitSkillData.normalSkill.UnitSkills.Add(skill);
					}
                }

                return unitSkillData;
            }
            catch (Exception err)
            {
                log.Error("createXmdsUnitSkillInfo error: " + err.Message, err);
                return null;
            }
        }
    }
}