require "StandardMouseButton"
require "CVector2"
require "CIrpMan"

-- reserve constructor
ConPanel = 
{
	name = "ConPanel"
}

if ( CFlowEffect == nil ) then
	CFlowEffect =
	{
		s_iEffectCount = 0
	}
end

function ConPanel:Create(  )
	
	-- The main screen container
	local instance = root.dialogs[ self.name ];
	CIrpMan:Attach( instance )
	
	-- The ok button
	local menuButton = instance.menubutton
	local timeDisplay = instance.timerText
	local winanim = false
	local wintimer = 0.0
	
	local clockInst = instance.clock
	local deciMinuteText = instance.clock.timeDeciMinute
	local minuteText = instance.clock.timeMinute
	local deciSecondText = instance.clock.timeDeciSecond
	local secondText = instance.clock.timeSecond
	local colonText = instance.clock.colon
	
	local pauseButton = instance.clock.pauseButton
	local cupid = instance.cupid
	--local clockHand = cupid.hand
	--local clockGlow = cupid.glow
	local lastsecond = -1;
	local clockframe = 0;
	
	local hintHandles = {}
	
	instance:SetOnUpdateEnabled( true );

	if ( IsRetail() == false ) then
		instance:AddAsGlobalHandler()
		function instance:OnCharDown( i_iChar )
			if ( i_iChar == 190 ) then		-- '.'
				log( "RELOAD LUA!" )
				console( "lua.dofile ConPanel.lua" )
			elseif ( i_iChar == 188 ) then	-- ','
				log( "RELOAD ART!" )
				console( "library.reloadpackage concentration" )
			end
		end
	end	
	function instance:OnRightMouseDown()
		--[[
		if ( IsDebug() ) then
			-- for reloads ..
			for i in _LOADED do
				_LOADED[ i ] = nil
			end

			console( "lua.dofile ConPanel.lua" )

			CFlowEffect:Create( self, GetMouseX(), GetMouseY(), 40, 40, 0.8, false, "ClockParticle" )
		end
		--]]
	end


	function instance:EffectSrcX( i_srcX )
		self.m_iEffectSrcX = i_srcX;
	end
	function instance:EffectSrcY( i_srcY )
		self.m_iEffectSrcY = i_srcY;
	end
	function instance:EffectDestX( i_destX )
		self.m_iEffectDestX = i_destX;
	end
	function instance:EffectDestY( i_destY )
		self.m_iEffectDestY = i_destY;
	end
	
	function instance:UpdateClock()
		if ( instance.Relaxed ) then
			
			local iColor = 0x999999
			
			deciMinuteText:SetColor( iColor )
				minuteText:SetColor( iColor )
			deciSecondText:SetColor( iColor )
				secondText:SetColor( iColor )
				 colonText:SetColor( iColor )
			
			pauseButton:SetVisible( false )
			pauseButton:SetInputEnabled( false )
--			clockGlow:SetVisible( false )
--			clockGlow:SetInputEnabled( false )
		else
			deciMinuteText:SetColor( 0x000000 )
				minuteText:SetColor( 0x000000 )
			deciSecondText:SetColor( 0x000000 )
				secondText:SetColor( 0x000000 )
				 colonText:SetColor( 0x000000 )
			
			pauseButton:SetVisible( true )
				
			pauseButton:SetInputEnabled( true )
--			clockGlow:SetVisible( true )
--			clockGlow:SetInputEnabled( true )
		end
	end
			
	-- The main init function
	function instance:Init( )

		log ( "initing con panel" )
		
		instance:SetPosition( 0, 0 )
		
		self:UpdateClock()
		
		local minutes = math.max( 0, math.floor( instance.Time / 60 ) )
		local deciMin = math.max( 0, math.floor( minutes / 10 ) )
		local mins = math.max( 0, math.mod( minutes, 10 ) )
		local seconds = math.max( 0, math.floor( math.mod( instance.Time , 60 ) ) )
		local deciSec = math.max( 0, math.floor( seconds / 10 ) )
		local secs = math.max( 0, math.mod( seconds, 10 ) )
		
		deciMinuteText:SetText( tostring( deciMin ) )
			minuteText:SetText( tostring( mins ) )
		deciSecondText:SetText( tostring( deciSec ) )
			secondText:SetText( tostring( secs ) )
				
		-- turn any passed clouds to gold
		for i = 0, instance.honeymoonitems -1 , 1 do
			instance[ "cloud_"..i ]:SetPlaying( true )
		end
		
		-- light up any dots we've already passed
		local dot
		if ( instance.honeymoonitems > 0 ) then
			for i = 0, (instance.honeymoonitems * 10)-1, 1 do
				local dot = instance[ "dot" .. i ]
				dot:SetFrame( 1 )
			end
		end
		
		-- light up any remaining dots
		local base = instance.honeymoonitems * 10
		local increment = math.floor( self.PercentComplete * 10 )
		for i=0, increment, 1 do
			dot = instance[ "dot" .. (base + i) ]
			dot:SetFrame( 1 )
		end
		
		-- set the plane up properly
		local startFrame
		local lastFrame = self.planeTrack:FindFrameFromLabel( "track" .. instance.honeymoonitems )
		if ( instance.honeymoonitems == 0 ) then
			startFrame = instance.planeTrack:FindFrameFromLabel( "track" )
		else
			startFrame = instance.planeTrack:FindFrameFromLabel( "track" .. instance.honeymoonitems - 1 )
		end
		
		-- position the plane on the track
		instance.planeTrack:SetFrame( startFrame + ((lastFrame - startFrame) * self.PercentComplete) )
		
		
		instance:UpdateUI( )
		StandardMouseButton( menuButton );
		menuButton:Init( )
		StandardMouseButton( pauseButton );
		pauseButton:Init( )
	end
	

	
	function instance:Lose()
	
		-- turn off all dots
		local base = instance.honeymoonitems * 10
		local increment = math.floor( self.PercentComplete * 10 )
		for i=0, 9, 1 do
			dot = instance[ "dot" .. (base + i) ]
			dot:SetFrame( 0 )
		end
		
		-- find the plane's starting position
		local startFrame
		if ( instance.honeymoonitems == 0 ) then
			startFrame = instance.planeTrack:FindFrameFromLabel( "track" )
		else
			startFrame = instance.planeTrack:FindFrameFromLabel( "track" .. instance.honeymoonitems - 1 )
		end
		
		-- position the plane on the track
		instance.planeTrack:SetFrame( startFrame )
	end
	
	function instance:PlayMatchAnimTimeBonus()
		self:PlayMatchAnim( "ClockParticle", 0.8, false )
	end

	function instance:PlayMatchAnim( i_sParticleName, i_fScaling, i_bAdjColor )
		if ( i_sParticleName == nil ) then
			i_sParticleName = "HeartParticle"
			i_fScaling = 0.7
			i_bAdjColor = true
		end

		self:CreateParticleEffect( "explode", "", self.m_iEffectSrcX, self.m_iEffectSrcY )
		
		local fDestX = 0
		local fDestY = 0
		
		CFlowEffect:Create( self, 
							self.m_iEffectSrcX, 
							self.m_iEffectSrcY, 
							0, 
							0,
							i_fScaling,
							i_bAdjColor,
							i_sParticleName )
			
	end
	
	
	function instance:PlayPlaneAnim()
		
		local base = instance.honeymoonitems * 10
		local increment = math.floor( self.PercentComplete * 10 )
		local dot
		
		if ( self.PercentComplete < 1.0 ) then
			-- turn on the current dot
			dot = instance[ "dot" .. (base + increment) ]
			
			dot:SetFrame( 1 )
		else
			-- make sure the last dot gets turned on
			increment = 9
			dot = instance[ "dot" .. (base + increment) ]
			dot:SetFrame( 1 )
			
			-- run the big sun animation when we finish the last leg of the cloud 9 trip
			if ( instance.honeymoonitems == 8 ) then
				log ( "playing sun animation..." )
				self:PlaySunAnim()
			end
		end
		
		self:FinishPlaneAnim()
		
	end
	
	function instance:FinishPlaneAnim()
		if ( instance.planeMovement ~= nil ) then
			self:KillIrp( instance.planeMovement )
		end
		
		-- find all the relevant frames for this animation
		local currFrame = self.planeTrack:GetFrame()
		
		local startFrame
		if ( instance.honeymoonitems == 0 ) then
			startFrame = instance.planeTrack:FindFrameFromLabel( "track" )
		else
			startFrame = instance.planeTrack:FindFrameFromLabel( "track" .. instance.honeymoonitems - 1 )
		end
		
		local lastFrame = self.planeTrack:FindFrameFromLabel( "track" .. instance.honeymoonitems )
		
		local destFrame = startFrame + ((lastFrame - startFrame) * self.PercentComplete)
		
		-- create the irp from the current frame to the destination
		instance.planeMovement = self:CreateIrp( currFrame, destFrame , 2.0, CIrpFuncs.mLinear, 2.0 )
		
		-- set up the callbacks
		instance.planeMovement.m_oHookContext = self

		instance.planeMovement.mOnChange = function( i_oIrp, conPanelContext )
		
			local newFrame = math.floor( i_oIrp:GetVal() )
			
			-- only update if the irp output is enough to move us to a new frame
			if ( newFrame ~= conPanelContext.planeTrack:GetFrame() ) then
			
				-- advance to the next frame
				conPanelContext.planeTrack:SetFrame( i_oIrp:GetVal() )

			end
		end
		
		-- delete self when done
		instance.planeMovement.mOnComplete = function( i_oIrp, conPanelContext )
			conPanelContext.planeMovement = nil
		end
	end
	
	
	
	

	function instance:PlaySunAnim()
		-- bail if we are already running the sun animation
		if ( instance.sunAnimation ~= nil ) then
			return
		end
		
		-- get rid of the plane, we are done with it
		instance.planeTrack.plane:SetVisible(false)
		
		-- a pair of irps to fade the sun in and rotate it
		instance.sunFadeIn = self:CreateIrp( 0, 1 , 1.0, CIrpFuncs.mLinear, 0 )
		instance.sunAnimation = self:CreateIrp( 0, -2 , 5.0, CIrpFuncs.mLinear, 0 )
		
		-- create the pieces of the animation...
		-- create the mask layer
		instance.sunAnimation.mask = self:CreateInstance( "sunmask", "sunMask" )
		instance.sunAnimation.mask:SetPosition( 2, 165 )

		--- create the sun
		instance.sunAnimation.sun = self:CreateInstance( "sun", "animatingSun" )
		instance.sunAnimation.sun:SetPosition( 45, 140 )
		instance.sunAnimation.sun:SetOpacity( 0 )

		-- create the clear layer
		instance.sunAnimation.clear = self:CreateInstance( "BlackBack", "sunMaskClear" )
		instance.sunAnimation.clear:SetPosition( 0, 165 )

		--- order the layers behind the highest cloud
		instance.sunAnimation.mask:MoveToFront()
		instance.sunAnimation.sun:MoveToFront()
		instance.sunAnimation.clear:MoveToFront()
		instance.cloud_8:MoveToFront()
		instance.planeTrack:MoveToFront()

		-- set up the masking
		instance.sunAnimation.mask:ToggleMaskBase( true )
		instance.sunAnimation.sun:ToggleMaskOut( true )
		instance.sunAnimation.clear:ToggleMaskClear( true )
		instance.sunAnimation.clear:SetVisible( false )
		
		-- set up the callbacks for the Sun Fade In
		instance.sunFadeIn.m_oHookContext = self
		instance.sunFadeIn.mOnChange = function( i_oIrp, conPanelContext )
			conPanelContext.sunAnimation.sun:SetOpacity( i_oIrp:GetVal() )
		end
		instance.sunFadeIn.mOnComplete = function( i_oIrp, conPanelContext )
			conPanelContext.sunAnimation.sun:SetVisible( true )
			conPanelContext.sunFadeIn = nil
		end
		
		-- set up the callbacks for the Sun Rotation
		instance.sunAnimation.m_oHookContext = self

		instance.sunAnimation.mOnChange = function( i_oIrp, conPanelContext )
			conPanelContext.sunAnimation.sun:SetRotation( i_oIrp:GetVal() )
		end
		instance.sunAnimation.mOnComplete = function( i_oIrp, conPanelContext )
			-- actually, dont delete the sun, it looks weird
			-- just let everything stay until the whole conpanel gets trashed.
		end
			
	end	
	
	-- The help button
	function menuButton:Init( )
		function menuButton:Pressed( )
			instance:ScreenEvent( "Menu" , "ConPanel" )
		end
	end
		-- The help button
	function pauseButton:Init( )
		function pauseButton:Pressed( )
			instance:ScreenEvent( "PauseGame" , "ConPanel" )
		end
--		function clockGlow:OnLeftMouseUp( )
--			instance:ScreenEvent( "PauseGame", "ISpyPanel" )
--		end	
	end
	function instance:OnUpdate( )
	
		self:UpdateIrps( 1 / 60 )
	
		self:UpdateClock()
		
		local minutes = math.floor( instance.Time / 60 )
		local seconds = math.floor( math.mod( instance.Time , 60 ) )
		local secondsStr = tostring( seconds );
		
		if( seconds <= 9 ) then
			secondsStr = "0"..seconds;
		end
			
		local minutes = math.max( 0, math.floor( instance.Time / 60 ) )
		local deciMin = math.max( 0, math.floor( minutes / 10 ) )
		local mins = math.max( 0, math.mod( minutes, 10 ) )
		local seconds = math.max( 0, math.floor( math.mod( instance.Time , 60 ) ) )
		local deciSec = math.max( 0, math.floor( seconds / 10 ) )
		local secs = math.max( 0, math.mod( seconds, 10 ) )
		
		deciMinuteText:SetText( tostring( deciMin ) )
			minuteText:SetText( tostring( mins ) )
		deciSecondText:SetText( tostring( deciSec ) )
			secondText:SetText( tostring( secs ) )
			
		--[[
		if( lastsecond ~= seconds ) then
			lastsecond = seconds
			clockframe = clockframe + 1
			
			if( clockframe >= 60 ) then
				clockframe = 1;
			end
--			clockHand:SetFrame( clockframe )
		end
		--]]
		

		instance:UpdateUI( )
	end
	
	function instance:UpdateUI( )
			
		if( wintimer > 0.0 ) then
			wintimer = wintimer - ( 1.0/60.0 )
			
			if( winanim and wintimer <= 0.0 ) then	
				winanim = false
				wintimer = 1.4
				--instance[ "cloud_"..( instance.honeymoonitems ) ]:SetPlaying( true )
				
			elseif( winanim == false and wintimer <= 0.0 ) then
				instance:ScreenEvent( "ShowWinDialog", "ConPanel" )
			end
		end
		
	end
	
	
	function instance:ClearItem()
		
	end
	
	function instance:DoItem( )
		wintimer = 1.4
		winanim = true
		
		local oBackMovie = root.ConBoard.item
		if ( oBackMovie ~= nil ) then
			require "MiniGameEffects"
			DoTraceEffect( oBackMovie, oBackMovie.object, "PMTrace" )
		end
	end
	

end

function CFlowEffect:Create( i_oParent, i_fSrcX, i_fSrcY, i_fDestX, i_fDestY, i_fScaling, i_bAdjColor, i_sParticleName )
	local oRet = CFlowEffect:Bind( {} )
	oRet:Init( i_oParent, i_fSrcX, i_fSrcY, i_fDestX, i_fDestY, i_fScaling, i_bAdjColor, i_sParticleName )
	return oRet
end

function CFlowEffect:Init( i_oParent, i_fSrcX, i_fSrcY, i_fDestX, i_fDestY, i_fScaling, i_bAdjColor, i_sParticleName )
	self.m_oParent = i_oParent
	
	for i = 1, 5, 1 do 
		CFlowEffect.s_iEffectCount = CFlowEffect.s_iEffectCount + 1
		
		local oInst = self.m_oParent:CreateInstance( i_sParticleName, "flowEffectParticle" .. CFlowEffect.s_iEffectCount )

		oInst:SetX( i_fSrcX + math.random( -50, 50 ) )
		oInst:SetY( i_fSrcY + math.random( -50, 50 ) )
		oInst:SetOpacity( 0 )
		oInst.m_oParent = self.m_oParent
		
		oInst:SetVisible( false )
		
		if ( i_bAdjColor ) then
			local iColor = math.random( 220, 255 ) * 0x10000 --+ math.random( 1, 64 ) * 0x100
			oInst:SetColor( iColor )
		end

		--[[
		local aQuadLoc = { { -1, -1 }, { -1, 1 }, { 1, -1 }, { 1, 1 } }
		for j = 1, table.getn( aQuadLoc ), 1 do
			local oSubInst = oInst:CreateInstance( i_sParticleName, "sub" .. j )
			oSubInst:SetX( aQuadLoc[ j ][ 1 ] )
			oSubInst:SetY( aQuadLoc[ j ][ 2 ] )
			oSubInst:SetColor( 0 )
			oSubInst:MoveToBack()
		end
		--]]
		
		local iRand = math.random( 1, 4 )
		if ( iRand == 1 ) then
			i_fDestX = -100
			i_fDestY = math.random( -100, 700 )
		elseif ( iRand == 2 ) then
			i_fDestX = 900
			i_fDestY = math.random( -100, 700 )
		elseif ( iRand == 3 ) then
			i_fDestX = math.random( -100, 900 )
			i_fDestY = 700		
		elseif ( iRand == 4 ) then
			i_fDestX = math.random( -100, 900 )
			i_fDestY = 700		
		end

		
		oInst.m_oSrc = CVector2:Create( oInst:GetX(), oInst:GetY() )
		oInst.m_oDelta = CVector2:Create( i_fDestX + math.random( -10, 10 ) - oInst:GetX(), 
							i_fDestY + math.random( -10, 10 ) - oInst:GetY() )
							
		oInst.m_oNormal = CVector2:Create( -oInst.m_oDelta.Y, oInst.m_oDelta.X )
		oInst.m_oNormal:NormalizeTo( 50 )
		oInst.m_fRotationStart = math.random( -20, 20 ) * 3.14 / 50
		oInst.m_fRotationSpeed = math.random( 50, 100 ) * 3.14 / 50
		if ( math.random( 0, 1 ) == 0 ) then
			oInst.m_fRotationSpeed = oInst.m_fRotationSpeed * -1
		end
		oInst:SetRotation( oInst.m_fRotationStart )
		
		oInst.m_fSkewVar = 1
		if ( math.random( 0, 1 ) == 0 ) then
			oInst.m_fSkewVar = -1
		end
		oInst.m_fSkewVar = oInst.m_fSkewVar * math.random( 100, 800 ) / 1000

		-- must be done in this order for it to work!
		local fRandWait = math.random( 0, 10 ) * 0.005
		local fAlphaSpeed = 0.3
		local fSpeed = math.max( 0.3, 0.002 * oInst.m_oDelta:GetMagnitude() )

		local oAlphaIrp = self.m_oParent:CreateIrp( 0, 1, fAlphaSpeed, CIrpFuncs.mEaseOutQuad, i * 0.04 + fRandWait )
		local oSkewIrp = self.m_oParent:CreateIrp( 0, 1, fSpeed, CIrpFuncs.mElastic, i * 0.1 + fRandWait )
		local oScaleIrp = self.m_oParent:CreateIrp( 0, i_fScaling, fSpeed, CIrpFuncs.mBounce, i * 0.1 + fRandWait )
		local oIrp = self.m_oParent:CreateIrp( 0, 1, fSpeed, CIrpFuncs.mLinear, i * 0.1 + fRandWait )

		--self.m_oParent:CreateParticleEmitter( "perfectMatchGlitter.xml", "perfectMatchGlitter", oInst:GetX(), oInst:GetY() );
		local effect = self.m_oParent:CreateParticleEffect( "perfectMatchGlitter", "", oInst:GetX(), oInst:GetY() );
		oInst.m_effectName = effect:GetName()
		--oInst.m_iEmitterId = self.m_oParent:GetLastEmitterId()

		oIrp.m_oHookContext = oInst

		oIrp.mOnChange = function( i_oIrp, i_oContext )

			i_oContext:SetX( i_oContext.m_oSrc.X + i_oContext.m_oDelta.X * i_oIrp:GetVal() )
			i_oContext:SetY( i_oContext.m_oSrc.Y + i_oContext.m_oDelta.Y * i_oIrp:GetVal() )
			i_oContext:SetRotation( i_oContext.m_fRotationStart + oInst.m_fRotationSpeed * i_oIrp:GetVal() )
		end

		oAlphaIrp.m_oHookContext = oInst

		oAlphaIrp.mOnChange = function( i_oIrp, i_oContext )
			i_oContext:SetOpacity( i_oIrp:GetVal() )
		end

		oScaleIrp.m_oHookContext = oInst

		oScaleIrp.mOnChange = function( i_oIrp, i_oContext )
			i_oContext:SetScale( 0.5 + i_oIrp:GetVal() * 2.5, 0.5 + i_oIrp:GetVal() * 2.5 )
		end


		oSkewIrp.m_oHookContext = oInst

		oSkewIrp.mOnChange = function( i_oIrp, i_oContext )

			i_oContext:SetX( i_oContext:GetX() + i_oContext.m_oNormal.X * i_oIrp:GetVal() * i_oContext.m_fSkewVar )
			i_oContext:SetY( i_oContext:GetY() + i_oContext.m_oNormal.Y * i_oIrp:GetVal() * i_oContext.m_fSkewVar )

			--i_oContext.m_oParent:MoveParticleEmitterById( i_oContext.m_iEmitterId,
			--												i_oContext:GetX(),
			--												i_oContext:GetY() )
			local effect = i_oContext.m_oParent[i_oContext.m_effectName]
			if (effect ~= nil) then
				effect:SelectRootParticle()
				effect:SetSelectedParticlePosition(i_oContext:GetX(), i_oContext:GetY(), true)
			end
		end

		oSkewIrp.mOnComplete = function( i_oIrp, i_oContext )

			i_oContext:DeleteSelf()
		end

		
	end
										
end


function CFlowEffect:Bind( i_oObj )
	BindObj( CFlowEffect, i_oObj )
	return i_oObj
end

ConPanel:Create()
