local p = {}

local Const = require("Module:Const/name")
local Power = require("Module:GongFa/power/data")
local Keys = require("Module:GongFa/key")
local Util = require('Module:Util')
local AttrData = require("Module:Const/attr").raw

function p.t(n)
	local function findOne(name)
		local query = require("Module:GongFa").db
		query.data0 = name
		local result = mw.huiji.db.findOne(query)
		return result
	end

    local gf = findOne(n or '洗髓经')

    mw.logObject(p.change(gf,true))
end

local function ToInt(n) --四舍六入五取偶
    local i0 = math.floor(n)
    local i1 = math.floor((n-i0)*10)
    if i1>5 then
        i0 = i0 + 1
    elseif i1==5 and i0%2 ==1 then
        i0 = i0 + 1
    end
    return i0
end

local function RequireName(i)
    if i < 500 then
    	if i < 60 then
    		return
    	end
        return Const.attr[i]
    elseif i < 600 then
        return Const.skill[i]
    else
        return Const.gongfa[i]
    end
end

local function Requirement(s)
	if type(s)~='string' then s = '0&0' end
    local arr = mw.text.split(s, '|', true)
    for k,v in ipairs(arr) do
        local pair = mw.text.split(v, '&', true)
        local id = tonumber(pair[1])
        local name = id>0 and RequireName(id) or '无'
        local value = ToInt(tonumber(pair[2])*150/5) * 5
        arr[k] = {name=name,value=value}
    end
    return arr
end

local function AttackTyp(s)
    local pair = mw.text.split(s, '|', true)
    local at = pair[1]
    at = tonumber(at)
    at = Const.attackTyp[at]
    local num = pair[2]
    num = tonumber(num)
    return at,num
end

local function GetAttrData() --返回一个数组,和id→index的映射
	local raw = AttrData
    local ids = {}
    local tmp = {}
    for _,v in ipairs(raw) do
        if v[7]==1 then
            table.insert(tmp, v)
            ids[v.id] = #tmp
        end
	end
	return tmp, ids
end

local function Format(value, attrDatum)
	if value==nil or value==0 then return nil end
	local color = Const.color[attrDatum[value>=0 and 3 or 4]]
	if attrDatum[1]==100 then
		value = string.format('%+0.2f', value)
	else
		value = string.format('%+d', value)
	end
	value = value..(type(attrDatum[2])=='string' and attrDatum[2] or '')
	return Util.color(value, color)
end

-- 合并百分比加成和固定值加成
local function Join(s1, s2)
	if type(s1)=='number' then --未经处理
		local function green(v, postfix)
			if v==0 then return end
			return Util.color('+'..v..(postfix or ''), Const.color[3])
		end
		s1 = green(s1, '%')
		s2 = green(s2)
	end

    if s1 and s2 then
        return s1..'※'..s2
    else
        if s1 or s2 then
        	return s1 or s2
        end
    end
end

local function run(gf, rate, merge)
    local new = {}
    local attrList, attrIdMap = GetAttrData()
    --计算所有属性
	for _, attrDatum in ipairs(attrList) do
		local key = attrDatum.id
        local value = gf[key]
        if value~=0 then
            value = value * rate / attrDatum[1]
            local name = attrDatum[0]
            if attrDatum[6] and attrDatum[6]>0 then
                name = name..'发挥'
            end
            new[merge and key or name] = value
        end
    end
    if not merge then
        new['全毒素抵抗'] = new['烈毒抵抗'] and new['赤毒抵抗']
        return new
    end
    --格式化
    for _, attrDatum in ipairs(attrList) do
        local key = attrDatum.id
        if new[key]~=0 then
            new[key] = Format(new[key], attrDatum)
        end
    end
    --将合并属性的固定值部分移入发挥部分
    for _, attrDatum in ipairs(attrList) do
        local id = attrDatum.id
        local id2 = attrDatum[6] --固定值id
        local index = attrIdMap[id2]
        if index then --是发挥
            attrList[index] = nil
            new[id] = Join(new[id], new[id2])
		end
	end
	--毒素合并
	local poisonCnt = 0
    for i=50041,50046 do
    	if new[i] then poisonCnt = poisonCnt + 1 end
    end
    if poisonCnt==6 then
    	attrList[attrIdMap[50041]][0] = '全毒素抵抗'
    	for i=50042,50046 do
	    	attrList[attrIdMap[i]] = nil
	    end
	end
    local ul = mw.html.create('ul')
    local cnt = 0
    for _, tuple in pairs(attrList) do --前面移除了部分,改用pairs
        local value = new[tuple.id]
        if value then
	        local name = tuple[0]
    		ul:node('\n')
	        ul:tag('li'):node(name..':'..value)
            cnt = cnt + 1
        end
    end
    if cnt==0 then return {} end
    return {['运功效果'] = tostring(ul:node('\n'))}
end

local function PicId(tuple)
	local qi = tuple[4] --功法属性
	local typ = tuple[1] --功法类型
	typ = (typ==-1 and 3) or (typ>2 and typ+1) or typ
	return qi*15+typ
end

function p.change(raw, merge, saveRaw)
	raw = require('Module:ParseData').one(raw)
    local level = raw[2]
    if level == 0 then error(mw.dumpObject(raw or 'nil')) end
    local levelRate = level>7 and 100 or 80
    local typ = raw[6] --运功位
    --运功
	local translated = run(raw, levelRate, merge)
    translated['门派'] = Const.gang[raw[3]]
    translated['品'] = mw.ustring.gsub(Const.level[level], '品$', '阶', 1)
    translated['类型'] = Const.gongfa[raw[1]]
    translated['属性'] = Const.qi[raw[4]]
    translated['图片'] = PicId(raw)
    translated['运功位'] = Const['运功位'][typ]
    translated['发挥上限'] = 100 + raw[711]*10
    --
    local list = {601,602,603,605, --功法命中
                  614,615,604, --破体破气伤害
                  41,42,43,44,45,46,47,48,49,50,51,52,53, --护体绝技
                  32,33,34,35, --身法
                  81,82,83,84,85,86 --毒
    }
    local rated = {}
    for _,v in ipairs(list) do
        rated[v] = raw[v]  * levelRate
    end
    rated[32] = rated[32] / 100
    rated[34] = rated[34] / 100

    for _,pair in ipairs(Keys.common) do
    	local name = pair[1]
    	local key = pair[2]
        translated[name] = rated[key] or raw[key]
    end
    local typKeys = Keys[typ]
    if typKeys then
        for _,pair in pairs(typKeys) do
	    	local name = pair[1]
	    	local key = pair[2]
            translated[name] = rated[key] or raw[key]
        end
    end

    if typ==3 then
        if merge then
        	translated['反击距离'] = string.format('%0.1f', (raw[55]) / 100)
        	for _,v in ipairs{'护体', '御气', '卸力', '拆招', '闪避'} do
        		local key1 = '绝技'..v
        		local key2 = key1..'发挥'
        		translated[key1] = Join(translated[key2], translated[key1])
        		translated[key2] = nil
        	end
        else
        	translated['反击距离'] = (raw[55]) / 100
        end
    elseif typ==2 then
    	if merge then
        	for _,v in ipairs{'速度','距离'} do
        		local key1 = '身法移动'..v
        		local key2 = key1..'发挥'
        		translated[key1] = Join(translated[key2], translated[key1])
        		translated[key2] = nil
        	end
        end
    elseif typ==1 then
    	if raw[1]==13 then --乐器
    		translated['内息占比'] = translated['力道占比']
    		translated['力道占比'] = 0
    	end
        if merge then
        	if raw[1]==5 then --腿法
        		translated['攻击距离'] = '2.0~'..string.format('%0.1f', raw[31]/100+4)
        	else
        		translated['攻击距离'] = '+'..string.format('%0.1f', raw[31]/100)
        	end
        	translated['伤害'] = string.format('%0.1f', rated[604] / 10)
        else
        	translated['伤害'] = rated[604] / 10
        	translated['攻击距离'] = raw[31] / 100
        end
        --毒
        local s = ''
        for i=81,86 do
            local value = rated[i]
            if value~=0 then
                local newKey = Const.poison[i-81]
                local c = {20008,20006,20005,20010,20004,20007}
                c = c[i-80]
                if merge then
                	s = s..'<li>含有'..newKey..':'..Util.color(value, Const.color[c])..'</li>'
                else
                	translated[newKey] = value
                end
            end
        end
        if s~='' then translated['毒素'] = s end
        --招式
        local cnt = 0
        for i=11,13 do
			local text = raw[i]
            if text=='0|0' or type(text)~='string' then break end
            local at,num = AttackTyp(text)
            cnt = cnt + num
            if merge then
                translated['招式'..(i-10)] = at
                translated['数量'..(i-10)] = num
            else
                translated[at] = num
            end
        end
        translated['招式'] = cnt
        --部位
        local sum = 0
        local bodyList = {}
        for i=21,30 do
            local bodyCnt = raw[i]
            if bodyCnt~=0 then
                local bodyName = Const.body[i-21]
                translated[bodyName] = bodyCnt
                sum = sum + bodyCnt
                table.insert(bodyList, bodyName..bodyCnt)
            end
        end
        translated['部位'] = sum
        translated['部位倾向'] = table.concat(bodyList, ' ')
    elseif typ==0 or typ==-1 then
        --万用格
        local sum = 0
        for i=901,910 do
            sum = sum + raw[i]
        end
        if sum~=0 then
            translated['万用格'] = sum
        end
        for i=921,924 do
            local value = raw[i]
            if value~=0 then
                local newKey = Const['运功位'][i-920]..'格'
                translated[newKey] = value
            end
        end
        --内力
        local qiRate = raw[4]==0 and 200 or 100 -- 混元翻倍
        for i=701,705 do
            local value = raw[i]
            if value~=0 then
                local newKey = Const.qi[i-700]..'内力'
                translated[newKey] = value * qiRate
            end
        end
    end
    --需求
    local requireList = Requirement(raw[710])
    if merge then
        local ul = mw.html.create('ul')
        local cnt = 0
        for _,pair in ipairs(requireList) do
        	if pair.value>0 then
        		ul:node('\n')
        		ul:tag('li'):node(pair.name..':'..Util.color(pair.value))
            	cnt = cnt + 1
            end
        end
        if cnt>0 then translated['需求'] = tostring(ul:node('\n')) end
    else
        for _,pair in ipairs(requireList) do
            translated[pair.name..'需求'] = pair.value
        end
    end

    --时间
    local time = raw[10]
    if typ==1 then
        translated['施展时间'] = ToInt(40 + time*0.25)
    elseif typ==2 or typ==3 then
        translated['施展时间'] = ToInt(20 + time*0.25)
    end
    --消耗
    local magic = raw[8]
    local sum = raw[9]
    translated['提气'] = magic * sum / 100
    translated['架势'] = (100 - magic) * sum / 100
    if raw[103]>0 then
    	if Power[raw[103]] and Power[raw[104]] == nil then
    		error(mw.dumpObject(raw))
    	end
	    translated['心法正练'] = Power[raw[103]][1]
	    translated['心法逆练'] = Power[raw[104]][1]
	end
	if saveRaw then
		return require('Module:Union'){translated, raw, default=0}
	end
    return translated
end

function p.allKeys()
	local result = {}
	for _,list in ipairs{Const.attr, Const.skill, Const.gongfa} do
		for _, v in pairs(list) do
			result[v..'需求'] = 1
		end
	end
	for _,v in ipairs{'护体', '御气', '卸力', '拆招', '闪避'} do
		v = '绝技'..v
		result[v] = 1
		result[v..'发挥'] = 1
	end
	for _,v in ipairs{'速度','距离'} do
		v = '身法移动'..v
		result[v] = 1
		result[v..'发挥'] = 1
	end
	for _,list in ipairs{Const.poison, Const.attackTyp, Const.body} do
		for _,v in pairs(list) do
			result[v] = 1
		end
	end
	for _,v in pairs(Const['运功位']) do
		result[v..'格'] = 1
	end
	for _,v in pairs(Const.qi) do
		result[v..'内力'] = 1
	end
	for _,v in pairs{
		'门派', '品级', '类型', '属性', '图片',
		'反击距离', '攻击距离', '伤害', '毒素', '需求',
		'施展时间', '提气', '架势', '心法正练', '心法逆练'
	} do
		result[v] = 1
	end

	local attrData = GetAttrData()
	for _,attr in ipairs(attrData) do
		if result[attr[0]] == 1 then
			result[attr[0]..'发挥'] = 1
		else
			result[attr[0]] = 1
		end
	end

	for _,list in pairs(Keys) do --prop
		for _, pair in ipairs(list) do
			result[pair[1]] = 1
		end
	end
	return result
end

return p
avatar