----------------------------------
-- 人物属性

-- doCalc 				重算人物属性
-- doCalcHero 			重算英雄属性 并赋值到human缓存中
-- calcMonsterConf		重算怪物属性 返回属性列表attrs
-- calcHeroGrid 		根据英雄grid重算英雄属性 返回属性列表attrs
-- updateValue 			更新属性
-- calcZhandouli 		根据属性计算战力
-- calcPingFen          计算评分

----------------------------------

local RoleExcel = require("excel.role")
local HeroExcel = require("excel.hero").hero
-- local skillExcel = require("excel.skill").skill
local MonsterExcel = require("excel.monster").monster
local MonsterAttrExcel = require("excel.monster").monsterAttr
local BattleMonsterExcel = require("excel.battlemonster")
local BattleMonsterExcel2 = require("excel.battlemonster2")
local Util = require("common.Util")
local BeSkill = require("combat.BeSkill")
local RoleHeadLogic = require("role.RoleHeadLogic")
local FuwenLogic = require("fuwen.FuwenLogic")
local HeroLogic = require("hero.HeroLogic")
local HeroEquip = require("hero.HeroEquip")
local RoleDefine = require("role.RoleDefine")
local TheStarsLogic = require("theStars.TheStarsLogic")
local UnionTecLogic = require("union.UnionTecLogic")
local MoshouLogic = require("moshou.MoshouLogic")
local UnionLivenessLogic = require("union.UnionLivenessLogic")
local ChengjiuLogic = require("chengjiu.ChengjiuLogic")
local AssessExcel = require("excel.assess")
local EquipExcel = require("excel.equip")
local FuwenExcel = require("excel.fuwen")
local RoleStrongLogic = require("role.RoleStrongLogic")
local ItemDefine = require("bag.ItemDefine")
local EquipLogic = require("equip.EquipLogic")
local CombatPosLogic = require("combat.CombatPosLogic")
local CombatDefine = require("combat.CombatDefine")
local RoleRealmLogic = require("roleSystem.RoleRealmLogic")
local TalismanLogic = require("talisman.TalismanLogic")
local HeroExclusiveWeapon = require("hero.HeroExclusiveWeapon")
local WinnerRelicLogic = require("winnerRelic.WinnerRelicLogic")
local HeroPubLogic = require("hero.HeroPubLogic")
local HeroSeed = require("hero.HeroSeed")
local ElfLogic = require("elf.ElfLogic")
local HeroTianYuan = require("hero.HeroTianYuan")
local HeroArtifacts = require("hero.HeroArtifacts")
local RecycleItem = require("bag.RecycleItem")


local function printAttr(attr, szText)
	for i = RoleDefine.ATK, RoleDefine.SPEED, 1 do
		print(szText.."[printAttr] i = "..i .." value = "..attr[i].."\n")
	end
	print("\n")
end

-- 计算人数属性
function doCalc(human)
	human.attr = human.attr or {}
	human.heroAttrs = human.heroAttrs or {}
	Util.cleanTable(human.attr)

	local attr = human.attr
	-- 取个人前六英雄的战斗力
	local zhandouli = CombatPosLogic.getCombatHeroZDL(human, CombatDefine.COMBAT_TYPE1)
	local lvConfig = RoleExcel.exp[human.db.lv+1]

	-- 人物属性	
	attr[RoleDefine.LEVEL] = human.db.lv
	attr[RoleDefine.EXP] = human.db.exp		
	attr[RoleDefine.EXP_MAX] = lvConfig and lvConfig.exp or 0
	attr[RoleDefine.ZUANSHI] = human.db.zuanshi
	attr[RoleDefine.JINBI] = human.db.jinbi
    attr[RoleDefine.FRIENDHEART] = human.db.friendHeart
	attr[RoleDefine.ZHANDOULI] = zhandouli
	human.db.zhandouli = zhandouli
	
    RoleStrongLogic.doCalcMoShouPingFen(human, attr)
end

function cleanHeroAttrCache(human)
	human.heroAttrs = {}
end

-- 重算英雄属性
function doCalcHero(human, index)
	local heroGrid = human.db.heroBag[index]
	local attrs = calcHeroGrid(heroGrid, index, human)	
	if not attrs then return end
    
    RoleStrongLogic.doCalcMoShouPingFen(human, attrs)
	human.heroAttrs = human.heroAttrs or {}
	human.heroAttrs[index] = human.heroAttrs[index] or {}
	Util.copyTableSimple(attrs, human.heroAttrs[index])	
end

-- 获取怪物属性 用的地方有点多，不一定改
function calcMonsterConf(monsterID, attrID, attrInput)
	local monsterConfig = MonsterExcel[monsterID] or BattleMonsterExcel.monster[monsterID] or BattleMonsterExcel2.monster[monsterID]
	local attrsConfig = attrID and MonsterAttrExcel[attrID]
	if not attrsConfig then
		-- attrsConfig = attrID and BattleMonsterExcel.monsterAttr[attrID]
		attrsConfig = attrID and (BattleMonsterExcel.monsterAttr[attrID] or BattleMonsterExcel2.monsterAttr[attrID])
	end

	if not attrsConfig then
		attrID = 1
		attrsConfig = MonsterAttrExcel[attrID]
	end
	
	local attrs = {}
	initCombatAttr(attrs)
	attrs[RoleDefine.INIT_MP] = 50
	attrs[RoleDefine.JINGZHUN] = RoleDefine.DEFAUT_MINGZHONG
    attrs[RoleDefine.BAOJI_HURT_RATE] = RoleDefine.DEFAUT_BAOJI_HURT_RATE

	-- 怪物基础属性
	if attrInput then
		for _, attr in ipairs(attrInput) do
			local key = attr[1]
			local value = attr[2]
			attrs[key] = (attrs[key] or 0) + value
		end
	else
		for _, attr in ipairs(attrsConfig.attrs) do
			local key = attr[1]
			local value = attr[2]
			attrs[key] = (attrs[key] or 0) + value
		end
	end
	
	-- 怪物被动技能属性
	BeSkill.doCalcHero(nil, attrs, nil, monsterConfig)
	checkLimit(attrs)
	attrs[RoleDefine.ZHANDOULI] = calcZhandouli(attrs)
	return attrs
end

-- 根据英雄grid重算英雄属性
-- 如果新增加了模块用于HERO_OTHER_ATTRS计算属性, 需要同步到 CombatLogic中的FieldsCombat 
local TEMP_HERO_ATTRS = {}
local HERO_BASE_ATTRS = {}
local HERO_OTHER_ATTRS = {}
function calcHeroGrid(heroGrid, index, human)
	if type(heroGrid) ~= "table" then 
		return 
	end

	initCombatAttr(TEMP_HERO_ATTRS)
	initCombatAttr(HERO_BASE_ATTRS)	
	initCombatAttr(HERO_OTHER_ATTRS)
	HERO_BASE_ATTRS[RoleDefine.INIT_MP] = 50
    -- 默认命中100% 暴击伤害
    HERO_BASE_ATTRS[RoleDefine.JINGZHUN] = RoleDefine.DEFAUT_MINGZHONG
    HERO_BASE_ATTRS[RoleDefine.BAOJI_HURT_RATE] = RoleDefine.DEFAUT_BAOJI_HURT_RATE

	--不同模块在英雄属性计算 begin
	HeroLogic.doCalcHero(heroGrid, HERO_BASE_ATTRS) -- 基础属性
	-- 防止循环引用
	local SkinLogic = require("skin.SkinLogic")
	--local heroSkinID, heroSkinSkill = SkinLogic.checkHeroSkin(human, index) 
	if human and human.db and human.db.skinBag then -- 皮肤属性
		--HeroLogic.doCalcHeroSkin(heroSkinID, HERO_OTHER_ATTRS)
		SkinLogic.doCalcSkinHero(human,HERO_BASE_ATTRS)
	end
	BeSkill.doCalcHero(heroGrid, HERO_BASE_ATTRS) -- 被动技能属性
	HeroEquip.doCalcHero(human, heroGrid, HERO_OTHER_ATTRS) -- 装备
    FuwenLogic.doCalcHero(heroGrid, HERO_OTHER_ATTRS) -- 符文	
	UnionTecLogic.doCalcHero(human, heroGrid, HERO_OTHER_ATTRS) -- 公会科技	
	RoleHeadLogic.doCalcHero(human, HERO_OTHER_ATTRS) --称号
	UnionLivenessLogic.doCalcHero(human, HERO_OTHER_ATTRS) --公会活跃等级
	ChengjiuLogic.doCalcHero(human, HERO_OTHER_ATTRS) --成就属性加成
	MoshouLogic.doCalcHero(human, heroGrid, HERO_OTHER_ATTRS) -- 魔兽	

	RoleRealmLogic.doCalcHero(human, HERO_OTHER_ATTRS) --境界

	TalismanLogic.doCalcHero(human, heroGrid, HERO_OTHER_ATTRS) --秘宝

	HeroExclusiveWeapon.doCalcHero(human, heroGrid, HERO_OTHER_ATTRS) -- 专属武器
	WinnerRelicLogic.doCalcHero(human, heroGrid, HERO_OTHER_ATTRS) --圣者遗物

	HeroPubLogic.doCalcHero(human, HERO_OTHER_ATTRS) --英雄酒馆
	HeroSeed.doCalcHero(human, heroGrid, HERO_OTHER_ATTRS) -- 英雄种子
	ElfLogic.doCalcHero(human, HERO_OTHER_ATTRS) --精灵系统
	HeroTianYuan.doCalcHero(human, heroGrid, HERO_OTHER_ATTRS) -- 英雄天元
	HeroArtifacts.doCalcHero(human, heroGrid, HERO_OTHER_ATTRS) -- 英雄神威灵装
	RecycleItem.doCalcHero(human, HERO_OTHER_ATTRS) -- 收纳箱
	
	--不同模块在英雄属性计算 end	
	
	-- 计算评分
    calcPingFen(human, heroGrid, HERO_OTHER_ATTRS)
	
	-- 最终计算
	calcFinalValue(HERO_BASE_ATTRS, HERO_OTHER_ATTRS, TEMP_HERO_ATTRS)
	
	heroGrid.zhandouli = TEMP_HERO_ATTRS[RoleDefine.ZHANDOULI] or 0
	return TEMP_HERO_ATTRS
end

-- 更新属性
function updateValue(k, v, attrs, isBuff)
	if k == RoleDefine.FANSHE_ZHUANGJIA then
		attrs[k] = v 			--反射装甲直接取值
	elseif isBuff then
		attrs[k] = (attrs[k] or 0) + v	--战斗中添加buff属性叠加全按累加方式计算
	else
		--if RoleDefine.isBasicRate(k) then
		--	attrs[k] = (10000 + attrs[k])*(10000 + v)/10000 - 10000 --几何计算
		--else
			attrs[k] = (attrs[k] or 0) + v	--累加计算
		--end
	end
end

-- 计算战力
function calcZhandouli(attrs)
	local zhandouli = 0
	for key, zdlcf in pairs(RoleExcel.zdlPoint) do
		local value = zdlcf.point
		if attrs[key] and attrs[key] > 0 then
            -- 减去默认命中 
            local attr = attrs[key]
            if key == RoleDefine.JINGZHUN then
               attr = attr - RoleDefine.DEFAUT_MINGZHONG
               attr = attr < 0 and 0 or attr
            end
            -- 减去默认爆伤
            if key == RoleDefine.BAOJI_HURT_RATE then
               attr = attr - RoleDefine.DEFAUT_BAOJI_HURT_RATE
               attr = attr < 0 and 0 or attr
            end
			zhandouli = zhandouli + attr * value
		end	
	end
	return math.ceil(zhandouli)
end


-- 计算英雄评分
function calcPingFen(human, heroGrid, attr)
    local heroConfig = HeroExcel[heroGrid.id]
	if not heroConfig then return end
	
	local totalPingFen = 0
	
	-- 英雄等级评分
	local lv = heroGrid.lv
	if not lv or lv <= 0 then
		lv = 1
	elseif lv > #AssessExcel.lv then
		lv = #AssessExcel.lv
	end
	local lvPingFen = AssessExcel.lv[lv].grade
	
	
	-- 英雄星级评分
	local star = heroGrid.star
	local starPingFen = AssessExcel.star[star].grade
	
	-- 英雄进阶评分
    local quality = heroGrid.quality
  	local qualityPingFen = AssessExcel.quality[quality] and AssessExcel.quality[quality].grade or 0
	
	-- 英雄装备评分
    local equipPingFen = 0
    if heroGrid.equip then
       local mathFloor = math.floor
	   for i = 1, ItemDefine.EQUIP_MAX_CNT do
           local equipGrid = heroGrid.equip[i]
           if equipGrid then
              local baseRate = EquipLogic.getEquipBaseRate(equipGrid.quality)
	   		  local equipConfig = EquipExcel.equip[equipGrid.id]
	   		  if equipConfig then
                 local score = equipConfig.score
                 score = mathFloor(score * baseRate)
	   		     equipPingFen = equipPingFen + score
	   		  end
	   	   end
	   end
    end
	
	-- 英雄符文评分
	local fuWenPingFen = 0
	for i = 1, 2 do
		if heroGrid.fuwen and 
           heroGrid.fuwen[i] and 
           heroGrid.fuwen[i].id ~= nil then
		    local  fuwenId = heroGrid.fuwen[i].id
            local skillLen = heroGrid.fuwen[i].skill and #heroGrid.fuwen[i].skill or 0
			for k = 1,skillLen do
				local skillID = heroGrid.fuwen[i].skill[k]
				local skillConfig = FuwenExcel.skill[skillID]
				fuWenPingFen = fuWenPingFen + AssessExcel.fuWen[skillConfig.lv].grade
			end
		end
	end
	
    -- 公会技能评分
    local unionTecPingFen = 0
    if human then
	   if human.db.unionUuid and human.db.unionUuid ~= "" and 
	   	human.db.technology and human.db.technology[heroConfig.job] then
           local technology = human.db.technology[heroConfig.job]  
           local techCfg = nil
	       for i = 1, UnionTecLogic.TEC_TIER_CNT do
	   	    local tech = technology[i]
               local assessCfg = AssessExcel.union[i]
	   	    if tech ~= nil and tech.lv ~= nil and tech.lv > 0 and assessCfg then
	   		    unionTecPingFen = unionTecPingFen + assessCfg.grade * tech.lv
               end
	   	end
       end
    end
	
	attr[RoleDefine.PINGFEN_LV] = lvPingFen
	attr[RoleDefine.PINGFEN_STAR] = starPingFen
	attr[RoleDefine.PINGFEN_JINJIE] = qualityPingFen
	attr[RoleDefine.PINGFEN_EQUIP] = equipPingFen
	attr[RoleDefine.PINGFEN_FUWEN] = fuWenPingFen
	attr[RoleDefine.PINGFEN_UNION] = unionTecPingFen
end

function getPointByKey(key)
	local cf = RoleExcel.zdlPoint[key]
	if not cf then return 0 end
	return cf.point
end

-- 某些属性是有上下限的
function checkLimit(attrs)
	attrs[RoleDefine.BAOJI] = math.max(attrs[RoleDefine.BAOJI], 0)
end

-- 计算最终属性
local CHECKNEGATIVE = {}
CHECKNEGATIVE[RoleDefine.STEAL_ATK] = 1
CHECKNEGATIVE[RoleDefine.STEAL_DEF] = 1
function calcFinalValue(heroAttrs, otherAttrs, attrs)
	heroAttrs[RoleDefine.ATK] = heroAttrs[RoleDefine.ATK] * (1 + heroAttrs[RoleDefine.ATK_RATE]/10000) * (1 + otherAttrs[RoleDefine.ATK_RATE]/10000)
	heroAttrs[RoleDefine.DEF] = heroAttrs[RoleDefine.DEF] * (1 + heroAttrs[RoleDefine.DEF_RATE]/10000) * (1 + otherAttrs[RoleDefine.DEF_RATE]/10000)
	heroAttrs[RoleDefine.HP] = heroAttrs[RoleDefine.HP] * (1 + heroAttrs[RoleDefine.HP_RATE]/10000) * (1 + otherAttrs[RoleDefine.HP_RATE]/10000)
	heroAttrs[RoleDefine.SPEED] = heroAttrs[RoleDefine.SPEED] * (1 + heroAttrs[RoleDefine.SPEED_RATE]/10000) * (1 + otherAttrs[RoleDefine.SPEED_RATE]/10000)
	otherAttrs[RoleDefine.ATK] = otherAttrs[RoleDefine.ATK] * (1 + otherAttrs[RoleDefine.ATK_RATE]/10000)
	otherAttrs[RoleDefine.DEF] = otherAttrs[RoleDefine.DEF] * (1 + otherAttrs[RoleDefine.DEF_RATE]/10000)
	otherAttrs[RoleDefine.HP] = otherAttrs[RoleDefine.HP] * (1 + otherAttrs[RoleDefine.HP_RATE]/10000)
	otherAttrs[RoleDefine.SPEED] = otherAttrs[RoleDefine.SPEED] * (1 + otherAttrs[RoleDefine.SPEED_RATE]/10000)
	for k,v in pairs(attrs) do
		attrs[k] = heroAttrs[k] + otherAttrs[k]
		if not CHECKNEGATIVE[k] then
			attrs[k] = math.max(attrs[k], 0)
		end
		attrs[k] = math.floor(attrs[k])
	end	
	attrs[RoleDefine.ATK_RATE] = 0
	attrs[RoleDefine.DEF_RATE] = 0
	attrs[RoleDefine.HP_RATE] = 0
	attrs[RoleDefine.SPEED_RATE] = 0
	checkLimit(attrs)
	attrs[RoleDefine.ZHANDOULI] = calcZhandouli(attrs)
end


-- 初始化属性
function initCombatAttr(attr)
	attr[RoleDefine.ZHANDOULI] = 0
	attr[RoleDefine.PINGFEN_LV] = 0
	attr[RoleDefine.PINGFEN_STAR] = 0
	attr[RoleDefine.PINGFEN_JINJIE] = 0
	attr[RoleDefine.PINGFEN_EQUIP] = 0
	attr[RoleDefine.PINGFEN_UNION] = 0
	attr[RoleDefine.PINGFEN_FUWEN] = 0
	attr[RoleDefine.PINGFEN_MOSHOU] = 0
	
	attr[RoleDefine.ATK] = 0
	attr[RoleDefine.DEF] = 0
	attr[RoleDefine.HP] = 0
	attr[RoleDefine.SPEED] = 0			
	attr[RoleDefine.SKILL_HURT_RATE] = 0
	attr[RoleDefine.JINGZHUN] = 0
	attr[RoleDefine.GEDANG] = 0
	attr[RoleDefine.BAOJI] = 0	
	attr[RoleDefine.BAOJI_HURT_RATE] = 0
	attr[RoleDefine.POJIA] = 0
	attr[RoleDefine.MIANKONG_RATE] = 0
	attr[RoleDefine.JIANSHANG_RATE] = 0
	attr[RoleDefine.SHENSHENG_HURT_RATE] = 0
	attr[RoleDefine.INIT_MP] = 0
	attr[RoleDefine.SHANBI] = 0
	attr[RoleDefine.KONG_RATE] = 0
	attr[RoleDefine.POJIA_DK] = 0

	attr[RoleDefine.ATK_RATE] = 0
	attr[RoleDefine.DEF_RATE] = 0
	attr[RoleDefine.HP_RATE] = 0
	attr[RoleDefine.SPEED_RATE] = 0
	attr[RoleDefine.XURUO] = 0
	attr[RoleDefine.JOB_HURT_RATE1] = 0
	attr[RoleDefine.JOB_HURT_RATE2] = 0
	attr[RoleDefine.JOB_HURT_RATE3] = 0
	attr[RoleDefine.JOB_HURT_RATE4] = 0
	attr[RoleDefine.JOB_HURT_RATE5] = 0
	attr[RoleDefine.STATUS_HURT_RATE1] = 0
	attr[RoleDefine.STATUS_HURT_RATE2] = 0
	attr[RoleDefine.STATUS_HURT_RATE3] = 0
	attr[RoleDefine.STATUS_HURT_RATE4] = 0
	attr[RoleDefine.STATUS_HURT_RATE5] = 0
	attr[RoleDefine.STATUS_HURT_RATE6] = 0
	attr[RoleDefine.STATUS_HURT_RATE7] = 0
	
	attr[RoleDefine.STATUS_BAOJI_RATE1] = 0
	attr[RoleDefine.STATUS_BAOJI_RATE2] = 0
	attr[RoleDefine.STATUS_BAOJI_RATE3] = 0
	attr[RoleDefine.STATUS_BAOJI_RATE4] = 0
	attr[RoleDefine.STATUS_BAOJI_RATE5] = 0
	attr[RoleDefine.STATUS_BAOJI_RATE6] = 0
	attr[RoleDefine.STATUS_BAOJI_RATE7] = 0
	attr[RoleDefine.STATUS_BAOJI_RATE8] = 0

	attr[RoleDefine.STATUS_MIANYI_RATE1] = 0
	attr[RoleDefine.STATUS_MIANYI_RATE2] = 0
	attr[RoleDefine.STATUS_MIANYI_RATE3] = 0
	attr[RoleDefine.STATUS_MIANYI_RATE4] = 0
	attr[RoleDefine.STATUS_MIANYI_RATE5] = 0
	attr[RoleDefine.STATUS_MIANYI_RATE6] = 0
	attr[RoleDefine.STATUS_MIANYI_RATE7] = 0
    attr[RoleDefine.STATUS_MIANYI_RATE8] = 0
    
	attr[RoleDefine.HP_ADD_RATE] = 0
	attr[RoleDefine.CHIXU_HURT_DEL_RATE] = 0
	attr[RoleDefine.ZAOCHENG_HP_ADD_RATE] = 0
	
	attr[RoleDefine.PHY_HURT_ADD_RATE] = 0
	attr[RoleDefine.MAGIC_HURT_ADD_RATE] = 0
	attr[RoleDefine.ANTI_BAOJI] = 0

	attr[RoleDefine.JIANSHANG_PHY_RATE] = 0
	attr[RoleDefine.JIANSHANG_MAGIC_RATE] = 0
	
	attr[RoleDefine.STEAL_ATK] = 0
	attr[RoleDefine.STEAL_DEF] = 0

	attr[RoleDefine.HURT_RATE] = 0
	attr[RoleDefine.BAOJI_HURT_RATE_EXTRA] = 0
	attr[RoleDefine.FANSHE_ZHUANGJIA] = 0
	attr[RoleDefine.HUDUN_COMBAT] = 0

	attr[RoleDefine.HURT_RATE_MAX] = 0

	attr[RoleDefine.STATUS_BAOJI_HURT_RATE1] = 0
	attr[RoleDefine.STATUS_BAOJI_HURT_RATE2] = 0
	attr[RoleDefine.STATUS_BAOJI_HURT_RATE3] = 0
	attr[RoleDefine.STATUS_BAOJI_HURT_RATE4] = 0
	attr[RoleDefine.STATUS_BAOJI_HURT_RATE5] = 0
	attr[RoleDefine.STATUS_BAOJI_HURT_RATE6] = 0
	attr[RoleDefine.STATUS_BAOJI_HURT_RATE7] = 0
	attr[RoleDefine.STATUS_BAOJI_HURT_RATE8] = 0

	attr[RoleDefine.ANTI_BAOJI_HURT_RATE] = 0

	attr[RoleDefine.JOB_JIANSHANG_RATE1] = 0
	attr[RoleDefine.JOB_JIANSHANG_RATE2] = 0
	attr[RoleDefine.JOB_JIANSHANG_RATE3] = 0
	attr[RoleDefine.JOB_JIANSHANG_RATE4] = 0
	attr[RoleDefine.JOB_JIANSHANG_RATE5] = 0
	attr[RoleDefine.ATK_JIANSHANG_RATE] = 0

	attr[RoleDefine.CAMP_JIANSHANG_RATE1] = 0
	attr[RoleDefine.CAMP_JIANSHANG_RATE2] = 0
	attr[RoleDefine.CAMP_JIANSHANG_RATE3] = 0
	attr[RoleDefine.CAMP_JIANSHANG_RATE4] = 0
	attr[RoleDefine.CAMP_JIANSHANG_RATE5] = 0
	
	attr[RoleDefine.CAMP_HURT_RATE1] = 0
	attr[RoleDefine.CAMP_HURT_RATE2] = 0
	attr[RoleDefine.CAMP_HURT_RATE3] = 0
	attr[RoleDefine.CAMP_HURT_RATE4] = 0
	attr[RoleDefine.CAMP_HURT_RATE5] = 0

    attr[RoleDefine.STATUS_DIKANG_RATE9] = 0
    attr[RoleDefine.AT_PHY_HURT_ADD_RATE] = 0
    attr[RoleDefine.AT_MAGIC_HURT_ADD_RATE] = 0
end
