require "common"
require "ui_common"

-------------------------------------------------------------------------------
-- constants
-------------------------------------------------------------------------------
c_PieceWobbleTime 	   = 0.5
c_WobbleFrequency 	   = 50.0
c_WobbleAmplitude 	   = 2.0
c_PieceFlySpeed 	   = 1500
c_DeltaTime 		   = 0.05
c_LoopDT    		   = 0.02
c_PenaltyPeriod 	   = 2.0
c_WrongClicksTolerated = 3
c_HintCooldownTime     = 30
c_DefaultPlayTime      = 10*60
c_PenaltyTime          = 20
c_PenaltyFlashOn       = 0.5
c_PenaltyFlashOff      = 0.5
c_PenaltyNumFlashes    = 4


-------------------------------------------------------------------------------
--  initialization
-------------------------------------------------------------------------------
tPieces = children( obj( "items" ) )
tTasks = {}

curTime 		= 0.0
bPaused       = false
lastMissTime 	= 0.0
nWrongClicks  = 0
nOpened       = 0
nToOpen       = 0
nPlayTime     = c_DefaultPlayTime
bPicking      = false
bWin          = false
nFishes       = 0

call ( "Fire_Hint", "play")
bRelaxMode    = false

function UpdateBonusButton()
    if nFishes == 1 then
        call ( "anmB01", "play" )
        wait ( 1 )
        set  ( "bBonus", "normalframe", "19" )
    elseif nFishes == 2 then 
        call ( "anmB02", "play" ) 
        wait ( 1 )
        set  ( "bBonus", "normalframe", "32" )
    elseif nFishes == 3 then 
        call ( "anmB03", "play" )
        wait ( 1 )
        set  ( "bBonus", "normalframe", "45" )        
        call ( "anmfire", "play" )
        set  ( "bBonus", "enabled", true )  
    end 
end

function OnBonusFish( item )
    set( item, "visible", "false" )
    nFishes = nFishes + 1
    UpdateBonusButton()
    
    if nFishes == 3 then 
        nFishes = 0
    end 
   
end

function HogInit()
    setObjects( tPieces, "visible", true )
    connectObjects( tPieces, "onlbup", "OnPieceClicked" )
    connect( "items", "onlbup", "OnMiss" )
    delObjects( children( objItemList ) )
    bRelaxMode = (get( "cbRelaxMode", "pressed" ) == "true")
    bWin = false
    bFinished = false
end

function UpdateStatusText()
    set( "FoundAmount", "text", "" .. nOpened .. "/" .. nToOpen )
end

function UpdateLabelText()
    for j, t in ipairs( tTasks ) do
        if (t.nPieces > 1) then
            set( t.objLabel, "text", t.sText .. "(" .. t.nPieces .. ")" )
        else
            set( t.objLabel, "text", t.sText )
        end
    end
end

function AllOpen()
    for j, t in ipairs( tTasks ) do
        if (t.nPieces > 0) then
            bAllOpen = false
            return false
        end
    end
    return true
end

function UpdateStatusText()
    set( "FoundAmount", "text", "" .. nOpened .. "/" .. nToOpen )
end

function OnMiss( item )
	if bPicking then
		return
	end
    
    if bRelaxMode then
        return
    end
	
    local dt = curTime - lastMissTime
	if (dt < c_PenaltyPeriod) then
		nWrongClicks = nWrongClicks + 1
		-- penalty click
		if nWrongClicks > c_WrongClicksTolerated then
            call ( "sndWrong", "play" )
            messageBox( "txtClickWarning", "txtWarning" )
			nWrongClicks = 0
            -- flash the timer
            local cTime = (c_PenaltyFlashOn + c_PenaltyFlashOff)*c_PenaltyNumFlashes
            bPaused = true
            while cTime > 0 do
                set( "TimeLeft", "visible", false )
                wait( c_PenaltyFlashOff )
                set( "TimeLeft", "visible", true )
                wait( c_PenaltyFlashOn )
                cTime = cTime - c_PenaltyFlashOn - c_PenaltyFlashOff
            end
            bPaused = false
            curTime = curTime + c_PenaltyTime
		end
	end
	lastMissTime = curTime
end

function HogGetHintPiece()
    local objPiece = nil
    for i = 1, #tPieces do
        local curPiece = tPieces[i]
        if (#tTasks == 0) then
            if (get( curPiece, "enabled" ) == "true" and 
                get( curPiece, "visible" ) == "true") then
                objPiece = curPiece
                break
            end
        else
            local sText = get( curPiece, "text" )
            for j, t in ipairs( tTasks ) do
                if not t.bHidden and not t.bComplete and 
                    t.sText == sText and get( curPiece, "visible" ) == "true" then
                    objPiece = curPiece
                end
            end
        end
        if (objPiece ~= nil) then
            break
        end
    end
    return objPiece
end

function ShowHint()
    local objPiece = HogGetHintPiece()
    local sx, sy = parseVec2( get( objPiece, "positionabs" ) )
    local objEffHint = obj( "effHint" )
    set( objEffHint, "position", "" .. sx .. "," .. sy )
    call( objEffHint, "play" )
end

function PlayHintCooldown()
    local cTime = 0.1
    local objProgress = obj( "progress" )
    local objHintBtn = obj( "Hint" )
    local objProgressBar = obj( "progressBar", objProgress )
    local barW = tonumber( get( objProgressBar, "width" ) )
    local objCaption = obj( "Caption", objProgress ) 
    set( objCaption, "Alpha", 0.2 )
    set( objProgressBar, "visible", true )
    set( objHintBtn, "enabled", false )
    while cTime < c_HintCooldownTime do
        set( objProgress, "width", barW*cTime/c_HintCooldownTime + 1 )
        wait( c_LoopDT )
        if not bPaused then 
            cTime = cTime + c_LoopDT
        end
    end
    set( objCaption, "Alpha", 1.0 )
    set( objProgressBar, "visible", false )
    set( objHintBtn, "enabled", true )
    set ( "Fire_Hint", "visible", "true" )
    call ( "sndHover", "Play" ) 
end

function OnHint()
    call ( "sndClick", "Play") 
    set ( "Fire_Hint", "visible", "false" )
    ShowHint()
    
    --  cooldown
    PlayHintCooldown()
end

function OnBonusHint()
    call ( "sndClick", "Play") 
    call ( "anmfire", "stop" )
    set  ( "bBonus", "normalframe", "1" )
    ShowHint()      
    set  ( "bBonus", "enabled", false )  
end

function HogUpdate()
    wait( c_LoopDT )
    bRelaxMode = (get( "cbRelaxMode", "pressed" ) == "true")
    if bRelaxMode then
        return
    end
    
    if not bPaused then
        curTime = curTime + c_LoopDT
    end
    local nSecondsLeft = nPlayTime - math.floor( curTime )
    local nSeconds = nSecondsLeft % 60
    local nMinutes = math.floor( nSecondsLeft/60 )
    sCurTime = "" .. nMinutes .. ":" .. string.format( "%02d", nSeconds )   
    set( "TimeLeft", "text", sCurTime )
    -- check for timeout
    if (nSecondsLeft <= 0.0) then
        messageBox( "txtTimeOut", "" )
        call( "error", "play" )
        bFinished = true
        bWin = false
    end
end

function HogAnimatePiece( objSrc, objDest )
    call( "effHint", "stop" )
    call( "sndItemRight", "play" )
    bPicking = true
    local sx, sy = parseVec2( get( objSrc, "positionabs" ) )
	local dx, dy = parseVec2( get( objDest, "positionabs" ) )
	dx = dx + tonumber( get( objDest, "width" ) )*0.5
	dy = dy + tonumber( get( objDest, "height" ) )*0.5
	
	local objFlyPiece = create( objSrc, "flypiece", obj( "flying_item" ) )
	set( objFlyPiece, "visible", "true" )
	set( objFlyPiece, "filterfont", "false" )
    
    objEffect = obj( "effFoundObject" )
    set( objEffect, "position", "" .. sx .. "," .. sy )
    call( objEffect, "play" )
	
	for ct = 0.0, c_PieceWobbleTime, c_DeltaTime do
		local t = ct/c_PieceWobbleTime
		local x = sx + c_WobbleAmplitude*math.sin( ct*c_WobbleFrequency )
		local y = sy 
		set( objFlyPiece, "position", x .. "," .. y )
		wait( c_DeltaTime )
	end
	bPicking = false
	
	local flyTime = vec2dist( sx, sy, dx, dy )/c_PieceFlySpeed
	for ct = 0.0, flyTime, c_DeltaTime do
		local t = ct/flyTime
		local x = lerp( dx, sx, t )
		local y = lerp( dy, sy, t )
		set( objFlyPiece, "position", x .. "," .. y )
		wait( c_DeltaTime )
	end
	
	delete( objFlyPiece )
end

function HogFinish()
    if bWin then
        call( "OnWin", "play" )
    else
        log( "not win" )
        setLocation( "worldmap" )
    end
end
