--[ =============================== Standard Move To Destination ================================ ]
--A script used to move an entity towards a given room, using the room's in-built patrol capabilities. This should
-- not include the player or things might behave oddly.
--Note: If gzTextVar.bOpenAndMoveInOneTurn is true, the entity will move through the door in one turn. This is used
-- during pursuits so the enemy cannot have the door slammed in their face.

--Argument Listing:
-- 0: iIndex - The entity index of the acting entity.
-- 1: sTargetRoom - Where the entity is trying to go.

--Arg check.
local iRequiredArgs = 2
local iArgs = LM_GetNumOfArgs()
if(iArgs < iRequiredArgs) then
	Debug_ForcePrint(fnResolvePath() .. ": Error, incorrect argument count. Got " .. iArgs .. " expected " .. iRequiredArgs .. ".\n")
	return
end

--Arg resolve.
local i = tonumber(LM_GetScriptArgument(0))
local sTargetRoom = LM_GetScriptArgument(1)

--[ =========================================== Setup =========================================== ]
--Resolve target room index.
local iTargetIndex = fnGetRoomIndex(sTargetRoom)
local sRoomName = gzTextVar.zEntities[i].sLocation
local iRoomIndex = fnGetRoomIndex(sRoomName)

--Entity check:
if(i < 1 or i > gzTextVar.zEntitiesTotal) then
    io.write("Warning: Entity " .. i .. " is out of range.\n")
    return
end

--Destination check:
if(iTargetIndex == -1) then
    io.write("Warning: Entity " .. i .. " " .. gzTextVar.zEntities[i].sDisplayName .. " is attempting to move to a location that does not exist: " .. sTargetRoom .. ".\n")
    return
end

--Get the first letter of matching movement.
local sPathInstructions = gzTextCon.zRoomList[iTargetIndex].zPathListing[iRoomIndex]
if(sPathInstructions == "" or sPathInstructions == nil) then return end
local sFirstLetter = string.sub(sPathInstructions, 1, 1)

--[ ===================================== Direction Resolver ==================================== ]
--Move in the requested direction:
local sDestination = "Null"
local iDestIndex = -1
local sArrivesFrom = "nowhere"
local sDepartsTo = "nowhere"
local sDoorCheck = "none"
if(sFirstLetter == "N") then
    sDestination = gzTextVar.zRoomList[iRoomIndex].sMoveN
    iDestIndex = gzTextVar.zRoomList[iRoomIndex].iMoveN
    sArrivesFrom = "the south"
    sDepartsTo = "to the north"
    sDoorCheck = gzTextVar.zRoomList[iRoomIndex].sDoorN
elseif(sFirstLetter == "S") then
    sDestination = gzTextVar.zRoomList[iRoomIndex].sMoveS
    iDestIndex = gzTextVar.zRoomList[iRoomIndex].iMoveS
    sArrivesFrom = "the north"
    sDepartsTo = "to the south"
    sDoorCheck = gzTextVar.zRoomList[iRoomIndex].sDoorS
elseif(sFirstLetter == "E") then
    sDestination = gzTextVar.zRoomList[iRoomIndex].sMoveE
    iDestIndex = gzTextVar.zRoomList[iRoomIndex].iMoveE
    sArrivesFrom = "the west"
    sDepartsTo = "to the east"
    sDoorCheck = gzTextVar.zRoomList[iRoomIndex].sDoorE
elseif(sFirstLetter == "W") then
    sDestination = gzTextVar.zRoomList[iRoomIndex].sMoveW
    iDestIndex = gzTextVar.zRoomList[iRoomIndex].iMoveW
    sArrivesFrom = "the east"
    sDepartsTo = "to the west"
    sDoorCheck = gzTextVar.zRoomList[iRoomIndex].sDoorW
elseif(sFirstLetter == "U") then
    sDestination = gzTextVar.zRoomList[iRoomIndex].sMoveU
    iDestIndex = gzTextVar.zRoomList[iRoomIndex].iMoveU
    sArrivesFrom = "below"
    sDepartsTo = "down"
elseif(sFirstLetter == "D") then
    sDestination = gzTextVar.zRoomList[iRoomIndex].sMoveD
    iDestIndex = gzTextVar.zRoomList[iRoomIndex].iMoveD
    sArrivesFrom = "above"
    sDepartsTo = "up"
end

--Failure:
if(sDestination == "Null") then
    return
end

--[ ======================================= Door Handling ======================================= ]
--Basic entity AI does the following: Open a closed door (ending the turn), move through the door, then shut it behind them.
-- When the door is locked, the AI checks if the player has the key. If the player does not have the matching key, we need
-- to move through the door but *not* allow the player to slip in after us. To this end, the AI will move through the door
-- and close it behind them in one action.
--If gzTextVar.bOpenAndMoveInOneTurn is true, the entity will not end its turn, regardless of the door's lock.
-- This is used during pursuits when the AI is adjacent to the player.
if(sDoorCheck ~= nil and sDoorCheck ~= "none") then

    --Variables.
    local sDoorState = string.sub(sDoorCheck, 1, 1)
    local sLockType = string.sub(sDoorCheck, 2)

    --If the door is a not-normal door, some extra checks must be done.
    if(sLockType ~= " Normal") then
        
        --If the player has the key to this door, then we don't need to do special checks. Who cares if the
        -- player slips in through a door they already had the key to, right?
        bOpenedDoor, sPrintString = fnCheckKeyStates(sLockType)
        if(bOpenedDoor == true) then
            
        --Player does not have the key. We need to move through the door without modifying its open state.
        else

            --If the character was in the same location as the player:
            if(gzTextVar.zEntities[i].sLocation == gzTextVar.gzPlayer.sLocation) then
                TL_SetProperty("Append", gzTextVar.zEntities[i].sDisplayName .. " goes " .. sDepartsTo .. ", closing the door behind them." .. gsDE)
                
            --If the arrival position is the same as the player's:
            elseif(sDestination == gzTextVar.gzPlayer.sLocation) then
                TL_SetProperty("Append", gzTextVar.zEntities[i].sDisplayName .. " arrives from " .. sArrivesFrom .. ", closing the door behind them." .. gsDE)
            end

            --Move indicators.
            local fOldX, fOldY, fOldZ = fnGetRoomPosition(gzTextVar.zEntities[i].sLocation)
            local fX, fY, fZ = fnGetRoomPosition(sDestination)
            TL_SetProperty("Move Entity Indicator", fOldX, fOldY, fOldZ, gzTextVar.zEntities[i].sIndicatorName, fX, fY, fZ)

            --Success! Move the character.
            gzTextVar.zEntities[i].sLocation = sDestination
            return
        end
    end

    --Okay, we can move through the door. Is it closed? Time to open it!
    if(string.sub(sDoorCheck, 1, 1) == "C") then
        
        --Setup.
        local sDirectionString = "Nowhere"
        if(sFirstLetter == "N") then
                    
            --Subroutine.
            LM_ExecuteScript(gzTextVar.sRootPath .. "Functions/Modify Door State.lua", sRoomName, "O" .. sLockType, "N", ciModifyVisibility, 0)
            
            --Store which direction we moved.
            sDirectionString = "south"
            gzTextVar.zEntities[i].sLastDoorDir = "SP"
            
        elseif(sFirstLetter == "S") then
                    
            --Subroutine.
            LM_ExecuteScript(gzTextVar.sRootPath .. "Functions/Modify Door State.lua", sRoomName, "O" .. sLockType, "S", ciModifyVisibility, 0)
            
            --Store which direction we moved.
            sDirectionString = "north"
            gzTextVar.zEntities[i].sLastDoorDir = "NP"
            
        elseif(sFirstLetter == "E") then
                    
            --Subroutine.
            LM_ExecuteScript(gzTextVar.sRootPath .. "Functions/Modify Door State.lua", sRoomName, "O" .. sLockType, "E", ciModifyVisibility, 0)
            
            --Store which direction we moved.
            sDirectionString = "west"
            gzTextVar.zEntities[i].sLastDoorDir = "WP"
            
        elseif(sFirstLetter == "W") then
                    
            --Subroutine.
            LM_ExecuteScript(gzTextVar.sRootPath .. "Functions/Modify Door State.lua", sRoomName, "O" .. sLockType, "W", ciModifyVisibility, 0)
            
            --Store which direction we moved.
            sDirectionString = "west"
            gzTextVar.zEntities[i].sLastDoorDir = "EP"
            
        end
        
        --The player will notice a door opening near them:
        if(sDestination == gzTextVar.gzPlayer.sLocation) then
            TL_SetProperty("Append", "A door opens to your " .. sDirectionString .. "." .. gsDE)
        end
        
        --End here. Opening a door burns a turn, if this flag is false.
        if(gzTextVar.bOpenAndMoveInOneTurn == false) then
            return
        end
    end
end

--[ ===================================== Display Handling ====================================== ]
--If the character was in the same location as the player:
if(gzTextVar.zEntities[i].sLocation == gzTextVar.gzPlayer.sLocation) then
    TL_SetProperty("Append", gzTextVar.zEntities[i].sDisplayName .. " goes " .. sDepartsTo .. "." .. gsDE)
    
--If the arrival position is the same as the player's:
elseif(sDestination == gzTextVar.gzPlayer.sLocation) then
    TL_SetProperty("Append", gzTextVar.zEntities[i].sDisplayName .. " arrives from " .. sArrivesFrom .. "." .. gsDE)
end

--Move indicators.
local fOldX, fOldY, fOldZ = fnGetRoomPosition(gzTextVar.zEntities[i].sLocation)
local fX, fY, fZ = fnGetRoomPosition(sDestination)
TL_SetProperty("Move Entity Indicator", fOldX, fOldY, fOldZ, gzTextVar.zEntities[i].sIndicatorName, fX, fY, fZ)

--Success! Move the character.
gzTextVar.zEntities[i].sLocation = sDestination

--Modify this flag on a successful move.
gzTextVar.zEntities[i].sLastDoorDir = string.sub(gzTextVar.zEntities[i].sLastDoorDir, 1, 1)
