local Config = require("Config")
local LuaMongo = _G.lua_mongo
local DB = require("common.DB")
local Util = require("common.Util")
local CommonDB = require("common.CommonDB")
local MiddleManager = require("middle.MiddleManager")
local InnerMsg = require("core.InnerMsg")
local CombatLogic = require("combat.CombatLogic")
local UnionWarLogic = require("union.UnionWarLogic")
local RobotExcel = require("excel.unionWar").robot
local UnionWarExcel = require("excel.unionWar")
local CombatDefine = require("combat.CombatDefine")
local RoleDefine = require("role.RoleDefine")

db = db or {upTime = nil,status = nil,unionList = {},log = {},localData = {}}
UNION_WAR_UPDATE_TIME = nil

local QueryByUuid = {}
local VideoQueryCond = {}

local UNIONWAR_UUID = "UNION_WAR"

function init()
	QueryByUuid.uuid = UNIONWAR_UUID
	LuaMongo.find(DB.db_union_war,QueryByUuid)
	if not LuaMongo.next(db) then
		clDB()
	end
end

function updateDB()
	QueryByUuid.uuid = UNIONWAR_UUID
	LuaMongo.update(DB.db_union_war, QueryByUuid, db)
end

function getDB()
	return db
end

function clDB()
	LuaMongo.remove(DB.db_union_war)
	LuaMongo.remove(DB.db_union_war_record)
	db = db or {localData = {}}
	db._id = nil
	db.isMatch = nil
	db.matchList = nil
	db.log = {}
	db.unionList = {}
	db.uuid = UNIONWAR_UUID
	LuaMongo.insert(DB.db_union_war, db)
end

function getLocalData()
	return db.localData
end

function addUnion(fd,msg)
	local svrIndex = MiddleManager.FD_2_SVRINDEX[fd]
	print(" midd addUnion ",  svrIndex)
	local len = #db.unionList
	for k,v in ipairs(msg.list) do
		len = len + 1
		db.unionList[len] = Util.copyTable(v)
		db.unionList[len].svrIndex = svrIndex
		db.unionList[len].log = {}
		db.unionList[len].star = 0
		db.unionList[len].jifen = 0
		db.unionList[len].combat = {}
		db.unionList[len].video = {}		
	end
	--updateDB()
end

function dismissUnion(uuid)
	if db.localData and db.localData[uuid] then
		db.localData[uuid] = nil
	end
end

function addUnionMember(fd,msg)
	print("  !!!!!!!!!! !addUnionMember  !!!!!!!!!!")
	local unionUuid = msg.unionUuid
	local union
	local len = #db.unionList
	for i = len ,1 ,-1 do
		if db.unionList[i].unionUuid == unionUuid then
			union = db.unionList[i]
			break
		end
	end
	if union then
		local member
		for k,v in ipairs(msg.list) do
			union.member[v[1]] = 1
			member = Util.copyTable(v[2]) 
			member.uuid = v[1]
			LuaMongo.insert(DB.db_union_war, member)
		end
		if msg.isEnd and msg.isEnd == 1 then			
		--	updateDB()
		end
	end

end

local function randomMonsterOutID(monsterOutIDList, index)
	local newID 
	newID = index > 1 and monsterOutIDList[index - 1] or monsterOutIDList[index + 1]
	if newID and newID > 0 then
		return newID
	end

	return math.random(10001, 10010)
end

local function addRobot(data1,data2)
	local cnt1 = data2.memberCnt + 1
	local cnt2 = data1.memberCnt
	local monsterOutIDList = {}
	local thisMember
	for k in pairs(data1.member) do
		thisMember = getMember(k)
		monsterOutIDList[thisMember.index] = thisMember.battleMonsterOutID
	end
	local member = {}
	for i = cnt1,cnt2 do
		local monsterOutID = monsterOutIDList[i]
		if not monsterOutID then
			monsterOutID = randomMonsterOutID(monsterOutIDList, i)
		end
		local objList, helpList, rolebase,formation = CombatLogic.getMonsterObjList(monsterOutID)
		data2.member[data2.unionUuid .. i] = 1
		member = {}
		member.uuid = data2.unionUuid .. i
		member.index = i
		member.monsterOutID = monsterOutID
		member.objList = objList
		member.helpList = helpList
		member.formation = formation
		member.rolebase = rolebase
		member.name = RobotExcel[i].name
		member.attackStar = 0
		member.defendStar = 3
		member.attackCnt = 0
		member.defendCnt = 0
		member.log = {}
		LuaMongo.insert(DB.db_union_war, member)
	end
end

local function addRobotByGm(data1,data2) 
	local monsterOutID = 1101
	local cnt1 = data2.memberCnt + 1
	local cnt2 = data1.memberCnt + 1
	for i = cnt1,  20 do
		local objList, helpList, rolebase,formation = CombatLogic.getMonsterObjList(monsterOutID)
		rolebase.uuid = data2.unionUuid .. i
		data2.member[data2.unionUuid .. i] = {index = i,monsterOutID = monsterOutID,objList = objList,helpList = helpList,formation = formation,rolebase = rolebase,name = RobotExcel[i].name, attackStar = 0,defendStar = 3,attackCnt = 0,defendCnt = 0,isRobot = 1,log = {}}
	end

	for i = cnt2,  20 do
		local objList, helpList, rolebase,formation = CombatLogic.getMonsterObjList(monsterOutID)
		rolebase.uuid = data1.unionUuid .. i
		data1.member[data1.unionUuid .. i] = {index = i,monsterOutID = monsterOutID,objList = objList,helpList = helpList,formation = formation,rolebase = rolebase,name = RobotExcel[i].name, attackStar = 0,defendStar = 3,attackCnt = 0,defendCnt = 0,isRobot = 1,log = {}}
	end
end

function match()
	if db.isMatch then
		return
	end
	table.sort(db.unionList,function(a,b)
		return a.zhandouli > b.zhandouli
	end	)
	local tmp = {}
	local matchData = {}
	-- 匹配非本服对手
	for i = 1,#db.unionList do
		local data1 = db.unionList[i]
		if not data1.targetID then
			for j = i+1,#db.unionList do
				local data2 = db.unionList[j]
				if data1.svrIndex ~= data2.svrIndex and not data2.targetID then
				--if not  data2.targetID then
					data1.targetID,data2.targetID = data2.unionUuid,data1.unionUuid
					if data1.memberCnt > data2.memberCnt then
						addRobot(data1,data2)
					elseif data1.memberCnt < data2.memberCnt then
						addRobot(data2,data1)
					end
					matchData[data1.unionUuid] = data2.unionUuid
					matchData[data2.unionUuid] = data1.unionUuid
					break
				end
			end
		end
		tmp[data1.unionUuid] = data1
	end

	-- 匹配剩下的 本服对手
	for i = 1,#db.unionList do
		local data1 = db.unionList[i]
		if not data1.targetID then
			for j = i+1,#db.unionList do
				local data2 = db.unionList[j]
				--if data1.svrIndex ~= data2.svrIndex and not data2.targetID then
				if not  data2.targetID then
					data1.targetID,data2.targetID = data2.unionUuid,data1.unionUuid
					if data1.memberCnt > data2.memberCnt then
						addRobot(data1,data2)
					elseif data1.memberCnt < data2.memberCnt then
						addRobot(data2,data1)
					end
					matchData[data1.unionUuid] = data2.unionUuid
					matchData[data2.unionUuid] = data1.unionUuid
					break
				end
			end
		end
		tmp[data1.unionUuid] = data1
	end

	db.unionList = tmp
	db.isMatch = true
	updateDB()

	matchToServer(matchData)

	if not db.matchList then
        db.matchList = {}
        local matchTmp = {}
        for k,v in pairs(db.unionList) do
            if not matchTmp[k] and v.targetID and db.unionList[v.targetID] then
                matchTmp[k] = 1
                matchTmp[v.targetID] = 1
                db.matchList[#db.matchList + 1] = {k,v.targetID}
            end
        end
    end
end

-- 降匹配成功的 公会发送给单服
function matchToServer(list)
	local msgRet = InnerMsg.wl.WL_UNION_WAR_MATCH_FINISH
	msgRet.list = Util.copyTable(list)

	for fd, _ in pairs(MiddleManager.FD_2_SVRINDEX) do
		InnerMsg.sendMsg(fd, msgRet)
	end
end

function getMember(uuid)
	local data = {}
	QueryByUuid.uuid = uuid
	LuaMongo.find(DB.db_union_war,QueryByUuid)
	if not LuaMongo.next(data) then
		return
	end
	return data
end

function updateMember(member)
	QueryByUuid.uuid = member.uuid
	LuaMongo.update(DB.db_union_war, QueryByUuid, member)
end

function addBuffLvByGm(unionUuid)
	local attackUnion = db.unionList[unionUuid]
	attackUnion.buffLv = attackUnion.buffLv or 0
	attackUnion.buffLv = attackUnion.buffLv + 1
end

-- 保存战斗记录
function setWarRecord(tb)
	LuaMongo.insert(DB.db_union_war_record, tb)
end

local QueryUionRecordByUuid = {}			--按uuid查询
local QueryUionRecord  = { atkUuid = nil, time = nil }
function queryRecord(atkUuid, time)
	QueryUionRecord.atkUuid = atkUuid
	QueryUionRecord.upTime = time
	local data = {}
    LuaMongo.find(DB.db_union_war_record, QueryUionRecord)
	if not LuaMongo.next(data) then
		return nil
	end
	return data, data._id
end

function getRecordDB(uuid)
	QueryUionRecordByUuid._id = uuid
	local data = {}
	LuaMongo.find(DB.db_union_war_record, QueryUionRecordByUuid)
	return LuaMongo.next(data) and data, nil
end

--战斗结束回调
--增加挑战次数，解锁防守对象，添加挑战日志，调整星数,积分,保存防守录像
function onFightEnd(msg)
	local attackUnion = db.unionList[msg.unionUuid]
	local defendUnion = db.unionList[attackUnion.targetID]
	local result = msg.combatInfo.isWin

	local attackUuid = msg.uuid
	local attacker = getMember(attackUuid)
	local combat = attackUnion.combat[attackUuid]
	if not combat then
		return
	end
	local defendUuid = combat[1]
	local defender = getMember(defendUuid)
	local diff = combat[2]
	local robotConf = RobotExcel[defender.index]
	local isFeixu = defender.defendStar <= 0
	local rate,star,jifen = UnionWarLogic.getDiff(robotConf,diff,defender.monsterOutID, isFeixu)

	attackUnion.combat[attackUuid] = nil
	local now = os.time()
	local tb = {}
	tb.upTime = now
	tb.attackUuid = attackUuid
	tb.defUud = defendUuid
	tb.diff = diff
	tb.combatInfo = Util.copyTable(msg.combatInfo)
	setWarRecord(tb)
	local recordIndex = tb._id
	db.log[#db.log + 1] = {now,result,msg.unionUuid,attackUnion.targetID,attackUuid,defendUuid,star,jifen,  msg.combatInfo.atkFormation , recordIndex}
	table.insert(attackUnion.log,1,#db.log)
	if #attackUnion.log > 150 then
		attackUnion.log[#attackUnion.log] = nil
	end
	table.insert(defendUnion.log,1,#db.log)
	if #defendUnion.log > 150 then
		defendUnion.log[#defendUnion.log] = nil
	end
	attacker.attackCnt = attacker.attackCnt + 1
	if msg.combatInfo.isWin then
		local oldOldStar = defender.defendStar
		star = star < oldOldStar and star or oldOldStar
		if star > oldOldStar then star = oldOldStar end
		attackUnion.star = attackUnion.star + star
		attackUnion.starUpTime = now
		defender.defendStar = defender.defendStar - star
		attacker.attackStar = attacker.attackStar + star		
		attacker.jifen = attacker.jifen + jifen
		attackUnion.jifen = attackUnion.jifen + jifen
		db.log[#db.log][#db.log[#db.log] + 1 ] = attacker.attackStar
		if oldOldStar == 0  and isFeixu then
			attackUnion.buffLv = attackUnion.buffLv or 0
			if attackUnion.buffLv < #UnionWarExcel.buff then
				attackUnion.buffLv = attackUnion.buffLv + 1
			end	
			defender.loseBuff = defender.loseBuff or 0
			defender.loseBuff = defender.loseBuff + 1

			-- 日志里 记录 攻击方 攻打废墟后 buffLV		
			db.log[#db.log][12] = attackUnion.buffLv
		end

		attacker.winLog = attacker.winLog or {}
		table.insert(attacker.winLog,1,#db.log)
		if #attacker.winLog > 20 then
			attacker.winLog[#attacker.winLog] = nil
		end

		defender.winLog = defender.winLog or {}
		table.insert(defender.winLog,1,#db.log)
		if #defender.winLog > 20 then
			defender.winLog[#defender.winLog] = nil
		end

	else
		defender.defendCnt = defender.defendCnt + 1
	end

	table.insert(defender.log,1,recordIndex)
	if #defender.log > 3 then
		defender.log[#defender.log] = nil
	end
	updateDB()
	updateMember(attacker)
	updateMember(defender)
	return attackUnion,defender,attacker.attackCnt,isFeixu, star, diff
end

function getMatchList()
    if not db.matchList then
		if not db.isMatch then
			return
		end
        db.matchList = {}
        local tmp = {}
        for k,v in pairs(db.unionList) do
            if not tmp[k] and v.targetID and db.unionList[v.targetID] then
                tmp[k] = 1
                tmp[v.targetID] = 1
                db.matchList[#db.matchList + 1] = {k,v.targetID}
            end
        end
    end
    return db.matchList,db
end

function actFinish()
	print(" union war ! actFinish actFinish !!!!!!! ")
	local sortList = {}
	local finishList = {}
	for k,v in pairs(db.unionList) do
		if not finishList[k] then    -- 防止重复 判定  同样的星级 0 0 时间下 俩个公会都会胜利
			local target = db.unionList[v.targetID]
			if target then
				local isWin = 1  -- 胜利
				local bWin = 2   -- 失败
				if target.star > v.star then
					isWin = 2
					bWin = 1
				elseif target.star == v.star then
					local aTime = v.starUpTime or 0 
					local bTime = target.starUpTime or 0
					if bTime > 0 and bTime < aTime then
						isWin = 2
						bWin = 1
					end
				end
				finishList[k] = true
				finishList[v.targetID] = true
				sortList[#sortList + 1] = {k,v.star,isWin,v.svrIndex}
				sortList[#sortList + 1] = {v.targetID,target.star, bWin,target.svrIndex}
			end			
		end		
	end
	table.sort(sortList,function(a,b)
		return a[2] > b[2]
	end)

	local msgRet = InnerMsg.wl.WL_UNION_WAR_ACTFINISH
	msgRet.list = sortList
    for fd in pairs(MiddleManager.FD_2_SVRINDEX) do
		InnerMsg.sendMsg(fd, msgRet)
	end
	updateDB()
end

--跨服整点逻辑（确定，匹配，结算）
function onHour(hour, isGm)	
	if not Config.IS_MIDDLE then return end
	local state = UnionWarLogic.getState()
	if state == UnionWarLogic.STATE0 then
		return 
	end
	if not (db.status and Util.isSameDay(db.upTime)) then
		if hour < UnionWarLogic.HOUR1[1] then
			db.status = 0
		elseif hour < UnionWarLogic.HOUR2[1] then
			db.status = 1		
		elseif hour < UnionWarLogic.HOUR4[1] then
			db.status = 2
		else
			db.status = 4
		end

		db.upTime = os.time()
		updateDB()
	end

	-- 防止 指定整点 逻辑没有过
	if hour == UnionWarLogic.HOUR1[1] or (hour > UnionWarLogic.HOUR1[1] and db.status < 1) then
		clDB()
		db.upTime = os.time()
		db.status = 1
        local msgRet =  InnerMsg.wl.WL_UNION_WAR_REFRESH
        for fd in pairs(MiddleManager.FD_2_SVRINDEX) do
			InnerMsg.sendMsg(fd, msgRet)
		end
    elseif hour >= UnionWarLogic.HOUR2[1] and db.status < 2 then
    	db.upTime = os.time()
    	db.status = 2
    	match()
    elseif hour >= UnionWarLogic.HOUR4[1] and db.status < 4 then
    	db.upTime = os.time()
    	db.status = 4
    	actFinish()
	end

end