-- 白夜苦行
local s,id,o=GetID()
local LIMIT_NUMBER=3
function c172016007.initial_effect(c)
	--redirect
	local e1=Effect.CreateEffect(c)
	e1:SetDescription(aux.Stringid(id,0))
	e1:SetType(EFFECT_TYPE_QUICK_O)
	e1:SetCode(EVENT_FREE_CHAIN)
	e1:SetRange(LOCATION_HAND)
	e1:SetCondition(s.limcon)
	e1:SetCost(s.limcost)
	e1:SetOperation(s.limop)
	c:RegisterEffect(e1)

	if not s.gf then
		-- Card.SetUniqueOnField 只涉及场上的卡
		-- Duel.RemoveCounter 目前为止只涉及场上的卡
		-- Duel.IsCanRemoveCounter 目前为止只涉及场上的卡
		-- Duel.GetCounter 目前为止只涉及场上的卡
		-- Duel.GetFieldGroup 已单独处理
		-- Duel.GetFieldGroupCount 已单独处理 
		s.hook_func2()
		Duel.GetMatchingGroup = s.hook_func("GetMatchingGroup",Duel.GetMatchingGroup,1,2,3,4)
		Duel.GetMatchingGroupCount = s.hook_func("GetMatchingGroupCount",Duel.GetMatchingGroupCount,1,2,3,4)
		Duel.GetFirstMatchingCard = s.hook_func("GetFirstMatchingCard",Duel.GetFirstMatchingCard,1,2,3,4)
		Duel.IsExistingMatchingCard = s.hook_func("IsExistingMatchingCard",Duel.IsExistingMatchingCard,1,2,3,4)
		Duel.SelectMatchingCard = s.hook_func("SelectMatchingCard",Duel.SelectMatchingCard,2,3,4,5)
		-- Duel.GetTargetCount 只涉及场上的卡
		-- Duel.IsExistingTarget 只涉及场上的卡
		-- Duel.SelectTarget 只涉及场上的卡
		-- Duel.GetOverlayGroup 似乎只涉及场上的卡
		-- Duel.GetOverlayCount 似乎只涉及场上的卡
		-- Duel.CheckRemoveOverlayCard 似乎只涉及场上的卡
		-- Duel.RemoveOverlayCard 似乎只涉及场上的卡
		-- Duel.SelectDisableField 只涉及场上的卡

		local ge=Effect.CreateEffect(c)
		ge:SetType(EFFECT_TYPE_FIELD+EFFECT_TYPE_CONTINUOUS)
		ge:SetCode(EVENT_CHAINING)
		ge:SetCountLimit(1,id)
		ge:SetCondition(s.gecon)
		ge:SetOperation(s.geop)
		Duel.RegisterEffect(ge,0)

		s.gf=true
	end
end

function s.limcon(e,tp,eg,ep,ev,re,r,rp)
	local ph=Duel.GetCurrentPhase()
	return Duel.GetFlagEffect(tp,id)==0 and Duel.GetTurnPlayer()~=tp and (ph==PHASE_MAIN1 or ph==PHASE_MAIN2)
end

function s.limcost(e,tp,eg,ep,ev,re,r,rp,chk)
	if chk==0 then return e:GetHandler():IsAbleToGraveAsCost() end
	Duel.SendtoGrave(e:GetHandler(),REASON_COST+REASON_DISCARD)
end

function s.limop(e,tp,eg,ep,ev,re,r,rp)
	local c=e:GetHandler()
	if Duel.SendtoHand(c,1-tp,REASON_EFFECT) then
		Duel.ResetFlagEffect(1-tp,id)
		local e1=Effect.CreateEffect(c)
		e1:SetType(EFFECT_TYPE_FIELD)
		e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET)
		e1:SetCode(id)
		e1:SetTargetRange(1,1)
		e1:SetReset(RESET_PHASE+PHASE_END)
		Duel.RegisterEffect(e1,tp)
		local e2=Effect.CreateEffect(e:GetHandler())
		e2:SetType(EFFECT_TYPE_FIELD+EFFECT_TYPE_CONTINUOUS)
		e2:SetCode(EVENT_FREE_CHAIN)
		e2:SetProperty(EFFECT_FLAG_EVENT_PLAYER+EFFECT_FLAG_IMMEDIATELY_APPLY)
		e2:SetCondition(aux.TRUE)
		e2:SetOperation(s.confirmop)
		e2:SetReset(RESET_PHASE+PHASE_END)
		Duel.RegisterEffect(e2,tp)
		local e3=e2:Clone()
		Duel.RegisterEffect(e3,1-tp)
	end
end

function s.confirmop(e,tp,eg,ep,ev,re,r,rp)
	local p=Duel.GetTurnPlayer()
	Duel.ConfirmCards(p,Duel.GetFieldGroup(p,LOCATION_DECK,0))
end

function s.gecon(e,tp,eg,ep,ev,re,r,rp)
	local ex2,g2,gc2,dp2,dv2=Duel.GetOperationInfo(ev,CATEGORY_SPECIAL_SUMMON)
	local ex3,g3,gc3,dp3,dv3=Duel.GetOperationInfo(ev,CATEGORY_TOGRAVE)
	local ex4=re:IsHasCategory(CATEGORY_DRAW)
	local ex5=re:IsHasCategory(CATEGORY_SEARCH)
	local ex6=re:IsHasCategory(CATEGORY_DECKDES)
	return ((ex2 and bit.band(dv2,LOCATION_DECK)==LOCATION_DECK)
		or (ex3 and bit.band(dv3,LOCATION_DECK)==LOCATION_DECK)
		or ex4 or ex5 or ex6) and Duel.IsChainDisablable(ev)
end

function s.geop(e,tp,eg,ep,ev,re,r,rp)
	if Duel.GetFlagEffect(rp,id)==0 then
		Duel.RegisterFlagEffect(rp,id,RESET_PHASE+PHASE_END,0,2)
	end
end

function s.hook_filter(f)
	if f==nil then
		return s.filter
	else
		return aux.AND(f,s.filter)
	end
end

function s.filter(c)
	return c:IsLocation(~LOCATION_DECK) or (s.OriginGetFieldGroupCount(c:GetOwner(),LOCATION_DECK,0)-c:GetSequence()<=LIMIT_NUMBER)
end

function s.hook_func(name,f,fpos,playerpos,lpos1,lpos2,addfilter)
	s["Origin"..name]=f
	return function(...)
		local args={...}
		local argc=select("#",...)
		if Duel.IsPlayerAffectedByEffect(args[playerpos],id) then
			if fpos~=nil then
				args[fpos] = s.hook_filter(args[fpos])
			end
			if lpos1~=nil and bit.band(args[lpos1],LOCATION_DECK)>0 then
				args[lpos1] = LOCATION_DECK	
			end
			if lpos2~=nil and bit.band(args[lpos2],LOCATION_DECK)>0 then
				args[lpos2] = LOCATION_DECK
			end
			return f(table.unpack(args,1,argc))
		else
			return f(...)
		end
	end
end

function s.hook_func2()
	s.OriginGetFieldGroup=Duel.GetFieldGroup
	s.OriginGetFieldGroupCount=Duel.GetFieldGroupCount
	Duel.GetFieldGroup = function(_player,_s,_o)
		if Duel.IsPlayerAffectedByEffect(_player,id) then
			if bit.band(_s,LOCATION_DECK)>0 then _s = LOCATION_DECK end
			if bit.band(_o,LOCATION_DECK)>0 then _o = LOCATION_DECK end
		end
		local group=s.OriginGetFieldGroup(_player,_s,_o)
		if Duel.IsPlayerAffectedByEffect(_player,id) then
			group=group:Filter(s.filter,nil)
		end
		return group
	end
--[[ 	Duel.GetFieldGroupCount = function(_player,_s,_o)
		if Duel.IsPlayerAffectedByEffect(_player,id) then
			if bit.band(_s,LOCATION_DECK)>0 then _s = LOCATION_DECK end
			if bit.band(_o,LOCATION_DECK)>0 then _o = LOCATION_DECK end
			local c1=s.OriginGetFieldGroupCount(_player,_s,0)
			local c2=s.OriginGetFieldGroupCount(_player,0,_o)
			if c1==LOCATION_DECK then c1=math.min(c1,LIMIT_NUMBER) end
			if c2==LOCATION_DECK then c2=math.min(c2,LIMIT_NUMBER) end
			return c1+c2
		else
			return s.OriginGetFieldGroupCount(_player,_s,_o)
		end
	end ]]
end
