require "CBook"

function lerp( a, b, delta )
	return (a * (1.0 - delta) + b * delta)
end
function normalize( a, b )
	local len = math.sqrt( a*a + b*b )
	return a/len, b/len
end


-- defaults (if not found)
local heartCorners = { { 320, 240 }, { 480, 240 }, { 480, 360 }, { 320, 360 }, { 320, 240 } }
local heartCenter = { 400, 300 }
local iHearts = 40

if ( IsSoftwareDevice() ) then
	iHearts = 26
end


local oSourceMovie
local bFromBook = true

if ( string.sub( transitionSceneSym, 1, 9 ) == "laceHeart" ) then
	oSourceMovie = root[ "StoryMiniGame" ][ transitionSceneSym ]
	transitionDone = false
	bFromBook = false
else
	local oPages = root.Book.pageLayout
	oSourceMovie = oPages.pageRight[ transitionSceneSym ]

	if ( oSourceMovie == nil ) then
		oSourceMovie = oPages.pageLeft[ transitionSceneSym ]
	end
end

if ( oSourceMovie == nil ) then
	log( " !!! Couldn't find source movie " .. transitionSceneSym )
else
	-- grab corner markers, do some quick validation, record results
	local newCorners = {}
	local i = 0
	while ( oSourceMovie[ "_cornerMarker" .. i ] ~= nil ) do
		local oMarker = oSourceMovie[ "_cornerMarker" .. i ]

		local xLoc = oMarker:GetX()
		local yLoc = oMarker:GetY()
log( "BLARG!" .. oSourceMovie:LocalToGlobalX( xLoc ) .. "," .. oSourceMovie:LocalToGlobalX( yLoc ) )
		table.insert( newCorners, { oSourceMovie:LocalToGlobalX( xLoc ), oSourceMovie:LocalToGlobalY( yLoc ) } )
		i = i + 1
	end
	
	-- only use new corners if all validate
	if ( table.getn( newCorners ) < 3 ) then
		log( " !!! Couldn't find more than 2 corners for photo " .. transitionSceneSym )
	else
		-- commit, dup first at end, find center
		heartCorners = newCorners

		local fSumX = 0
		local fSumY = 0
		
		for i = 1, table.getn( heartCorners ), 1 do
			fSumX = fSumX + heartCorners[ i ][ 1 ]
			fSumY = fSumY + heartCorners[ i ][ 2 ]
		end
		
		heartCenter = { fSumX / table.getn( heartCorners ), fSumY / table.getn( heartCorners ) }

		table.insert( heartCorners, heartCorners[ 1 ] )
	end
end

function DoTwinkles()
	
	root:CreateParticleEffect("Twinkles", "", 0, 0)
	fadePlane:MoveToFront()
	
	--[[
	local twinkMgr = root:CreateEmptyInstance( "twinkMgr" )
	twinkMgr.life = 4.0
	twinkMgr.radius = 400
	twinkMgr.particles = {}
	twinkMgr.particleIdx = 0
	twinkMgr:SetX( 0 )
	twinkMgr:SetY( 0 )
	twinkMgr.particleCreateCounter = 0
	
	twinkMgr:SetOnUpdateEnabled( true )
	
	function twinkMgr:OnUpdate()
		self.life = self.life - 1/60
		if self.life <= 0 then
			self:DeleteSelf()
		else
			-- create white particles a decreasing distance inwards from center
			self.particleCreateCounter = self.particleCreateCounter + 1
			if ( self.particleCreateCounter >= 2 ) then
				self.particleCreateCounter = 0
				local partOwner = self:CreateEmptyInstance( "partOwner" .. self.particleIdx )
				partOwner:SetRegistrationPoint( 8, 8 )
				local img = partOwner:CreateInstance( "Particles_StarSparkle.png", "particle" .. self.particleIdx )
				self.particleIdx = self.particleIdx + 1
				local randAngle = math.random( 0.0, 100 ) * math.pi * 0.02
				local delta = lerp( 1.0, 0.6, (1.0 - self.life/4) )
				--log( "randangle: " .. randAngle )
				partOwner:SetX( math.cos( randAngle ) * twinkMgr	.radius * delta + 400 )
				partOwner:SetY( math.sin( randAngle ) * twinkMgr.radius * delta + 300 )
				
				partOwner.time = 0.0
				
				partOwner:SetOnUpdateEnabled( true )
				
				function partOwner:OnUpdate()
					self.time = self.time + 1/60
					--self:SetOpacity( math.sin( self.time ) )
					self:SetScale( lerp( 1.0, 5.0, self.time/4 ), lerp( 1.0, 5.0, self.time/4 ) )
				end
			end
		end
	end
	--]]
end

function DoFade()
	fadeTransitionOut = false
	fadePlane.fadeInTime = 0.0
	fadePlane.fadeInTimeTotal = 2.5
	fadePlane.fadeOutTime = 0.0
	fadePlane.fadeOutTimeTotal = 2.5
	fadePlane:SetOpacity( 0.0 )
	
	
	fadePlane:SetOnUpdateEnabled( true )
	
	function fadePlane:OnUpdate()
	
		if ( fadeTransitionOut ) then
			self.fadeOutTime = self.fadeOutTime + 1/60
			local fLerp = self.fadeOutTime / self.fadeOutTimeTotal
		
			-- fadeout
			if fLerp >= 1 then
				self:DeleteSelf()
			else
				self:SetOpacity( math.max( math.pow( fLerp, 0.75 ), 0 ) )
			end
		else
			self.fadeInTime = self.fadeInTime + 1/60
			local fLerp = self.fadeInTime / self.fadeInTimeTotal

			-- fadein
			self:SetOpacity( math.min( math.pow( fLerp, 1.33 ), 1 ) )
		end
	end
end

function ShowLoading()
	fadePlane.time = 0.0
	fadePlane.lerpTotalTime = 0.5
	fadePlane.lerpTime = 0.0
	fadePlane.startFrame = fadePlane.plane:FindFrameFromLabel( "animLoadingFadeInStart" )
	fadePlane.endFrame = fadePlane.plane:FindFrameFromLabel( "animLoadingFadeInEnd" )
	
	function fadePlane:OnUpdate()
		self.lerpTime = self.lerpTime + 1/60
		if ( self.lerpTime >= self.lerpTotalTime ) then
			self.plane:SetFrame( self.endFrame )
		else
		log( "FRAME" .. tostring( self.startFrame + math.floor( ( self.lerpTime / self.lerpTotalTime ) * ( self.endFrame - self.startFrame ) ) ) )
			self.plane:SetFrame( self.startFrame + math.floor( ( self.lerpTime / self.lerpTotalTime ) * ( self.endFrame - self.startFrame ) ) )
		end
	end

end

function DoHearts()

-- VV Uncomment if want to use particles
--	root:CreateParticleEffect( "Explode1", "", heartCenter[1], heartCenter[2] );
--end

--function DoHearts1()

	-- positions for heart particles
	local heartSections = math.floor( iHearts / ( table.getn( heartCorners ) - 1 ) )
	local hearts = {}
	local heardSpeed = 2.5

	-- for each corner of heart area, trace a line of hearts
	local heardIdx = 0
	for hC in pairs( heartCorners ) do
	
		-- ignore last line
		if ( hC == table.getn( heartCorners ) ) then
			return
		end
		
		local lineStart = heartCorners[hC]
		local lineEnd = heartCorners[hC+1]
		
		for i = 0, heartSections, 1 do
			heardIdx = heardIdx + 1

			local fLerp = i / heartSections 
			
			-- get position f
			local x = lerp( lineStart[1], lineEnd[1], fLerp )
			local y = lerp( lineStart[2], lineEnd[2], fLerp )

			local heart = root:CreateEmptyInstance( "heart" .. heardIdx )
			-- if we could not create a heart instance, it means the previous ones have not died out, since it would be a duplicate name
			-- therefore just break out of the loop and ignore this transition effect request
			if( heart == nil ) then
				break
			end
				
			heart.m_oInner = heart:CreateEmptyInstance( "heart" )

			heart.m_fScaleBase = 1
			
			if ((i % 3) ~= 0) then			
				heart.m_oInner:CreateInstance( "petal_A_02_1.png", "inner" )
				
--				local randomLeafColor = math.random(4, 7)
--				if (randomLeafColor == 0) then
--					heart:SetColor(0xff804000)
--				elseif (randomLeafColor == 1) then
--					heart:SetColor(0xffe0a000)
--				elseif (randomLeafColor == 2) then
--					heart:SetColor(0xffc06000)
--				elseif (randomLeafColor == 3) then
--					heart:SetColor(0xffe02000)
--				else
--					heart:SetColor(0xff40d000) -- green is the default (more of them than the others)
--				end				
			else
				heart.m_oInner:CreateInstance( "petal_A_06_1.png", "inner" )
				heart.m_fScaleBase = 0.3
			end
			
			heart.curRotation = math.random(0.0, 2*math.pi);
			heart:SetRotation(heart.curRotation)
			heart.rotationRate = math.pi;
			if (math.random(0.0, 1.0) < 0.5) then
				heart.rotationRate = -heart.rotationRate;
			end

			heart:SetX( x )
			heart:SetY( y )

			-- backtrack a bit to center
			local x, y = heart:GetX(), heart:GetY()
			local dirX, dirY = x - heartCenter[1], y - heartCenter[2]

			dirX, dirY = normalize( dirX, dirY )

			heart:SetX( heart:GetX() - dirX * 50 )
			heart:SetY( heart:GetY() - dirY * 50 )

			--root:CreateParticleEmitter( "heartGlitter.xml", "heartGlitter", heart:GetX(), heart:GetY() );
			local effect = nil;
			if (i == 0) then
				effect = root:CreateParticleEffect( "heartGlitter", "", heart:GetX(), heart:GetY() );
				fadePlane:MoveToFront()
			else
				effect = root:CreateParticleEffectNoReload( "heartGlitter", "", heart:GetX(), heart:GetY() );
				fadePlane:MoveToFront()
			end
			heart.m_effectName = effect:GetName()
			--heart.m_iEmitterId = root:GetLastEmitterId()
			heart.life = 6.0
			heart.m_fSpeed = heardSpeed
			
			heart:MoveToFront()

			--heart.m_oInner:SetColor( 0xaa0000 )
			if ( math.mod( i, 2 ) == 1 ) then
				heart.m_fSpeed = heart.m_fSpeed - 0.2
				heart.m_fScaleBase = heart.m_fScaleBase * 0.8
				--heart.m_oInner:SetColor( 0xF58D7F )
			end
				--heart.m_oInner:SetColor( 0 x000000)

			heart:SetOnUpdateEnabled( true )
	
			function heart:OnUpdate()
				self.life = self.life - 1/60
				if self.life <= 0 then
					self:DeleteSelf()
				else
					-- fly out from center
					local x, y = self:GetX(), self:GetY()
					local dirX, dirY = x - heartCenter[1], y - heartCenter[2]
					dirX, dirY = normalize( dirX, dirY )
					--log( "dir: " .. dirX .. ", " .. dirY )
					self:SetX( x + dirX * self.m_fSpeed )
					self:SetY( y + dirY * self.m_fSpeed )
					
					--root:MoveParticleEmitterById( self.m_iEmitterId, self:GetX() + self:GetWidth() / 3, self:GetY() + self:GetHeight() / 3 )
					local effect = root[self.m_effectName]
					if (effect ~= nil) then
						effect:SelectRootParticle()
						effect:SetSelectedParticlePosition(self:GetX() + self:GetWidth() / 3, self:GetY() + self:GetHeight() / 3, true)
					end
					
					if ( heart.life > 5 ) then
						self:SetOpacity( ( 6 - heart.life ) / 1 )
					else
						self:SetOpacity( heart.life/6 )
					end
					self:SetScale( math.min( 0.1 + (1-heart.life/8), self.m_fScaleBase ) * 1.5, 
								   math.min( 0.1 + (1-heart.life/8), self.m_fScaleBase ) * 1.5 )
					
					self.curRotation = self.curRotation + (self.rotationRate / 60);
					self:SetRotation(heart.curRotation)
				end
			end 
		end
	end
end

function LoadLevel()
	log("calling transition done" )
	if ( bFromBook ) then
		CBook.G:TransitionDone()
	else
		transitionDone = true
	end

	-- fade the plane out and delete
	transitionMgr.time = 0
	fadePlane:SetOpacity( 1 )
	fadePlane:MoveToFront()
	
	function transitionMgr:OnUpdate()
		if ( fadeTransitionOut ) then

			self.time = self.time + 1/60
			if ( fadePlane ~= nil ) then
				fadePlane:SetOpacity( 1 - self.time )
			end
			if ( self.time >= 1.0 ) then
				if ( fadePlane ~= nil ) then
					fadePlane:DeleteSelf()
					fadePlane = nil
				end
				if ( transitionMgr ~= nil ) then
					transitionMgr:DeleteSelf()
					transitionMgr = nil
				end
			end
		end
	end
end

function StartTransition()
	-- make sure previous ones are deleted
	if ( fadePlane ~= nil ) then
		fadePlane:DeleteSelf()
		fadePlane = nil
	end
	if ( transitionMgr ~= nil ) then
		transitionMgr:DeleteSelf()
		transitionMgr = nil
	end
	
	-- first create fade plane so there is no hitch
	fadePlane = root:CreateEmptyInstance( "fadePlane" )
	fadePlane:CreateInstance( "whitePlane", "plane" )
	fadePlane:SetOpacity( 0.0 )
	
	-- create transition object
	transitionMgr = root:CreateEmptyInstance( "transitionMgr" )
	transitionMgr.time = 0
	
	if ( transitionSceneShowLoading ) then

		transitionMgr.states = 
		{
			{ 0.0, DoHearts },
			{ 0.25, DoTwinkles },
			{ 0.5, DoFade },
			{ 3.5, ShowLoading },
			{ 4.0, LoadLevel },
		}

	else

		transitionMgr.states = 
		{
			{ 0.0, DoHearts },
			{ 0.25, DoTwinkles },
			{ 0.5, DoFade },
			{ 4.0, LoadLevel },
		}
	end
	
	transitionMgr:SetOnUpdateEnabled( true )
	
	function transitionMgr:OnUpdate()
		local oldTime = self.time
		self.time = self.time + 1/60
		for s in pairs( self.states ) do
			local state = self.states[s]
			if oldTime <= state[1] and self.time > state[1] then
				state[2]()
			end
		end
	end
end

StartTransition()