Tutorial1 = {}

Tutorial1.Add = function()

end

Tutorial1.PreloadInit = function()
    local female = true;
    local desc = SurvivorFactory.CreateSurvivor(SurvivorType.Neutral, female);
    getWorld():setLuaPlayerDesc(desc);
    getWorld():getLuaTraits():clear();

    SandboxVars.Alarm = 1 -- Never
    SandboxVars.ZombieLore.ThumpNoChasing = true;
    SandboxVars.ZombieLore.DisableFakeDead = 3;
    SandboxVars.ZombieLore.Strength = 1;
    SandboxVars.ThumpOnConstruction = true;

    getCore():setAutoZoom(0, false) -- FIXME: save/restore this option?
end

Tutorial1.AddPlayer = function(p)

    if getCore():isDedicated() then return end

    p:setDir(IsoDirections.SE);
end

Tutorial1.closeBothInv = function()
    Tutorial1.closeLoot();
    Tutorial1.closeInv();
    getPlayer():setBannedAttacking(false);
end

Tutorial1.closeLoot = function()
    getPlayerLoot(0).blink = false;
    getPlayerLoot(0).inventoryPane.highlightItem = nil;
    if JoypadState.players[1] then
        getPlayerLoot(0):setVisible(false);
        setJoypadFocus(0, nil);
    else
        getPlayerLoot(0):collapse();
        getPlayerLoot(0).isCollapsed = true;
        getPlayerLoot(0):setMaxDrawHeight(getPlayerInventory(0):titleBarHeight());
    end
end

Tutorial1.closeInv = function()
    getPlayerInventory(0).blink = false;
    getPlayerInventory(0).inventoryPane.highlightItem = nil;
    if JoypadState.players[1] then
        getPlayerInventory(0):setVisible(false);
        setJoypadFocus(0, nil);
    else
        getPlayerInventory(0):collapse();
        getPlayerInventory(0).isCollapsed = true;
        getPlayerInventory(0):setMaxDrawHeight(getPlayerInventory(0):titleBarHeight());
    end
end

Tutorial1.createInventoryContextMenu = function(player, isInPlayerInventory, items ,x ,y)
    local context = ISContextMenu.get(player, x, y);
    context.blinkOption = ISInventoryPaneContextMenu.blinkOption;
    local testItem = nil;
    for i,v in ipairs(items) do
        if not instanceof(v, "InventoryItem") then
            testItem = v.items[1];
        end
    end
    if testItem then
        if Tutorial1.contextMenuEat and testItem:getType() == "DeadMouse" then
            local eatOption = context:addOption(getText("ContextMenu_Eat"), {testItem});
            local subMenuEat = context:getNew(context)
            context:addSubMenu(eatOption, subMenuEat)
            subMenuEat:addOption(getText("ContextMenu_Eat_All"), {testItem}, ISInventoryPaneContextMenu.onEatItems, 1, player);
            subMenuEat:addOption(getText("ContextMenu_Eat_Half"), {testItem}, ISInventoryPaneContextMenu.onEatItems, 0.5, player)
            subMenuEat:addOption(getText("ContextMenu_Eat_Quarter"), {testItem}, ISInventoryPaneContextMenu.onEatItems, 0.25, player)
        end
        if Tutorial1.contextMenuEquipPrimary and instanceof(testItem, "HandWeapon") then
            context:addOption(getText("ContextMenu_Equip_Primary"), {testItem}, ISInventoryPaneContextMenu.OnPrimaryWeapon, player);
        end
        if Tutorial1.contextMenuEquip2Hand and instanceof(testItem, "HandWeapon") then
            context:addOption(getText("ContextMenu_Equip_Two_Hands"), {testItem}, ISInventoryPaneContextMenu.OnTwoHandsEquip, player);
        end
        if Tutorial1.contextMenuEquipBag and instanceof(testItem, "InventoryContainer") and testItem:canBeEquipped() == "Back" and not getPlayer():isEquipped(testItem) then
            context:addOption(getText("ContextMenu_Equip_on_your_Back"), {testItem}, ISInventoryPaneContextMenu.onWearItems, player);
        end
        if Tutorial1.contextMenuWear then
            if instanceof(testItem, "Clothing") then
                if getSpecificPlayer(player):isEquipped(testItem) then
                    context:addOption(getText("ContextMenu_Unequip"), {testItem}, ISInventoryPaneContextMenu.onUnEquip, player);
                else
                    ISInventoryPaneContextMenu.doWearClothingMenu(player, testItem, items, context);
                end
                
                if testItem:getClothingItemExtraOption() then
                    ISInventoryPaneContextMenu.doClothingItemExtraMenu(context, testItem, getSpecificPlayer(player))
                end
            end
        end
    end
    return context;
end

Tutorial1.createWorldContextMenuFromContext = function(context, worldobjects)
    local chr = getPlayer();
    context.blinkOption = ISInventoryPaneContextMenu.blinkOption;
    local items = {};
    for i,v in ipairs(worldobjects) do
        for i=0,v:getSquare():getObjects():size()-1 do
            table.insert(items, v:getSquare():getObjects():get(i));
        end
    end
    local bottle = (chr:getInventory():FindAndReturn("WaterBottleEmpty") or chr:getInventory():FindAndReturn("WaterBottleFull"));
    for i,v in ipairs(items) do
        if Tutorial1.contextMenuFillBottle and v:hasWater() and bottle then
            context:addOption(getText("ContextMenu_Fill") .. bottle:getName(), worldobjects, ISWorldObjectContextMenu.onTakeWater, v, nil, bottle, chr:getPlayerNum());
            break;
        end
        if Tutorial1.contextMenuOpenCurtain and instanceof(v, "IsoCurtain") or (instanceof(v, "IsoWindow") and v:HasCurtains())then
            if instanceof(v, "IsoWindow") then
                v = v:HasCurtains();
            end
            local text = getText("ContextMenu_Open_curtains");
            if v:IsOpen() then
                text = getText("ContextMenu_Close_curtains");
            end
            if not context:getOptionFromName(text) then
                context:addOption(text, worldobjects, ISWorldObjectContextMenu.onOpenCloseCurtain, v, chr:getPlayerNum());
            end
            break;
        end
    end
    return context;
end

Tutorial1.createWorldContextMenu = function(player, worldobjects, x, y)
    local context = ISContextMenu.get(player, x, y);
    return Tutorial1.createWorldContextMenuFromContext(context, worldobjects);
    
end

-- Return true if the double-click was handled here.
-- Return false if ISInventoryPane should handle the double-click.
Tutorial1.doubleClickInventory = function(inventoryPane, x, y, mouseOverOption)
    if Tutorial1.steps == nil or Tutorial1.steps:isEmpty() then
        return false
    end
    if not inventoryPane.parent.onCharacter then
        return false
    end
    local item = inventoryPane.items[mouseOverOption]
    if not item then
        return false
    end
    if x < inventoryPane.column2 then
        -- Double-clicked the icon to expand/collapse a stack.
        return false
    end
    local items = ISInventoryPane.getActualItems({item})
    for _,item2 in ipairs(items) do
        if instanceof(item2, "HandWeapon") or not Tutorial1.contextMenuEquipPrimary then
            -- Disable double-click to equip or unequip.
            return true
        end
    end
    return false
end

Tutorial1.Init = function()

    Tutorial1.steps = LuaList:new();

    local m1 = Keyboard.getKeyName(getCore():getKey("Forward"))
    local m2 = Keyboard.getKeyName(getCore():getKey("Left"))
    local m3 = Keyboard.getKeyName(getCore():getKey("Backward"))
    local m4 = Keyboard.getKeyName(getCore():getKey("Right"))
    Tutorial1.moveKeys = getText("IGUI_Tutorial1_MovementKeys", m1, m2, m3, m4)

    -- climate
    local clim = getClimateManager();
    local w = clim:getWeatherPeriod();
    if w:isRunning() then
        clim:stopWeatherAndThunder();
    end
    
    -- remove fog
    local var = clim:getClimateFloat(5);
    var:setEnableOverride(true);
    var:setOverride(0, 1);
    
    local chr = getPlayer();
    local inv = chr:getInventory();
    
    local visual = chr:getHumanVisual();
    chr:setFemale(true);
    chr:getDescriptor():setFemale(true);
    chr:getDescriptor():setForename("Jane");
    chr:getDescriptor():setSurname("Doe");
    
    -- reset
    chr:clearWornItems();
    chr:getInventory():clear();
    visual:setSkinTextureIndex(2);
    
    -- chr visual
    local immutableColor = ImmutableColor.new(0.83, 0.67, 0.27, 1)
    visual:setHairModel("Longcurly");
    visual:setHairColor(immutableColor)

    chr:resetModel();
    
    local clothe = inv:AddItem("Base.Tshirt_DefaultTEXTURE_TINT");
    local color = ImmutableColor.new(1, 1, 1, 1)
    clothe:getVisual():setTint(color);
    clothe:synchWithVisual();
    chr:setWornItem(clothe:getBodyLocation(), clothe);
    clothe = inv:AddItem("Base.Shorts_ShortDenim");
    clothe:getVisual():setTextureChoice(2);
    clothe:synchWithVisual();
    chr:setWornItem(clothe:getBodyLocation(), clothe);
    clothe = inv:AddItem("Base.Socks_Ankle");
    clothe:synchWithVisual();
    chr:setWornItem(clothe:getBodyLocation(), clothe);
    clothe = inv:AddItem("Base.Shoes_BlueTrainers");
    clothe:synchWithVisual();
    chr:setWornItem(clothe:getBodyLocation(), clothe);

    chr:setInvincible(true);
    chr:setUnlimitedCarry(true);
    chr:setUnlimitedEndurance(true);

    -- board up all other windows
    Tutorial1.addBarricade(162, 157, 0);
    Tutorial1.addBarricade(158, 160, 0);
    Tutorial1.addBarricade(160, 152, 0);
    Tutorial1.addBarricade(154, 151, 0);
    Tutorial1.addBarricade(151, 151, 0);
    Tutorial1.addBarricade(153, 162, 0);
    Tutorial1.addBarricade(149, 162, 0);
    Tutorial1.addBarricade(147, 159, 0);
    Tutorial1.addBarricade(148, 151, 0);
    Tutorial1.addBarricade(147, 154, 1);
    Tutorial1.addBarricade(149, 151, 1);
    Tutorial1.addBarricade(154, 151, 1);
    Tutorial1.addBarricade(131, 179, 0);
    Tutorial1.addBarricade(129, 183, 0);
    BandageStep.barricadedWindow1 = Tutorial1.addMetalBarricade(179, 147, 0);
    BandageStep.curtain = BandageStep.barricadedWindow1:HasCurtains();
    BandageStep.curtain:ToggleDoorSilent();
    Tutorial1.addMetalBarricade(179, 150, 0);
    Tutorial1.addMetalBarricade(177, 153, 0);
    -- easter egg windows
    Tutorial1.addBarricade(195, 194, 0);
    Tutorial1.addBarricade(197, 199, 0);

    -- add trash can to block player when killing mom
--    local sq = getSquare(169, 157, 0);
--    sq:AddTileObject(IsoObject.getNew(sq, "street_decoration_01_26", nil, false));

    -- lock needed doors
    Tutorial1.lockDoor(131, 181, 0)
    SneakStep.fenceGate = Tutorial1.lockDoor(169, 145, 0)
    FightStep.lockedDoor = Tutorial1.lockDoor(163, 153, 0)
    FightStep.lockedDoor2 = Tutorial1.lockDoor(164, 153, 0)
    BandageStep.lockedDoor = Tutorial1.lockDoor(176, 153, 0)
    -- easter egg door
    Tutorial1.lockDoor(193, 194, 0)
    Tutorial1.lockDoor(106, 128, 0)

    -- gonna remove brothers fences to replace it with IsoThumpable
    Tutorial1.removeFences();
    
    addVehicleDebug("Base.PickupBurnt", IsoDirections.E, -1, getSquare(164, 160, 0));
    addVehicleDebug("Base.CarNormalBurnt", IsoDirections.NE, -1, getSquare(168, 160, 0));
    addVehicleDebug("Base.TaxiBurnt", IsoDirections.N, -1, getSquare(169, 155, 0));

    Tutorial1.marker = getWorldMarkers();

    -- open some doors
--    Tutorial1.openDoor(103, 124, 0, true)
--    Tutorial1.openDoor(106, 124, 0, true)
--    Tutorial1.openDoor(131, 181, 0, false)
    
    if JoypadState.players[1] then
        Tutorial1.joypad = true;
        JoypadState.disableGrab = true;
        JoypadState.disableInvInteraction = true;
        JoypadState.disableYInventory = true;
        JoypadState.disableControllerPrompt = true;
        JoypadState.disableMovement = true;
        JoypadState.disableClimbOver = true;
        JoypadState.disableSmashWindow = true;
        JoypadState.disableReload = true;
        ISBackButtonWheel.disablePlayerInfo = true;
        ISBackButtonWheel.disableCrafting = true;
        ISBackButtonWheel.disableTime = true;
        ISBackButtonWheel.disableMoveable = true;
        ISBackButtonWheel.disableZoomOut = true;
        ISBackButtonWheel.disableZoomIn = true;
        ISBackButtonWheel.disableScavenge = true;
    end
    
    
    Tutorial1.steps:add(WelcomeStep:new())
    Tutorial1.steps:add(WalkToAdjacent:new())
    Tutorial1.steps:add(InventoryLootingStep:new());
    Tutorial1.steps:add(InventoryUseStep:new());
    Tutorial1.steps:add(FightStep:new());
    Tutorial1.steps:add(SneakStep:new());
    Tutorial1.steps:add(BandageStep:new());
    Tutorial1.steps:add(ShotgunStep:new());

    Tutorial1.steps:get(0):begin();
    
    SurvivalGuideManager.blockSurvivalGuide = true;
    getPlayer():setCanShout(false);
    getPlayer():setAllowSprint(false);
    getCore():setCollideZombies(false);
    
    ISReloadWeaponAction.disableReloading = true;
    getPlayerInventory(0).transferAll:setVisible(false);
    getPlayerLoot(0).lootAll:setVisible(false);
    
    if SurvivalGuideManager.instance then
        SurvivalGuideManager.instance.panel:setVisible(false);
    end

    Events.OnTick.Add(Tutorial1.Tick)
--    Tutorial1.FillContainers();
end

Tutorial1.openDoor = function(x,y,z, north)
    local sq = getSquare(x, y, z);
    if sq and sq:getDoor(north) then
        local door = sq:getDoor(north);
        door:setLocked(false);
        door:setLockedByKey(false);
        door:ToggleDoorSilent();
    end
end

Tutorial1.collapseInv = function(inv)
    inv:collapse();
    inv.isCollapsed = true;
    inv:setMaxDrawHeight(inv:titleBarHeight());
end

Tutorial1.lockDoor = function(x, y, z)
    local sq = getSquare(x, y, z);
    for i=0, sq:getObjects():size() -1 do
        local obj = sq:getObjects():get(i);
        if instanceof(obj, "IsoDoor") then
            obj:setLockedByKey(true);
            obj:setLocked(true);
            return obj;
        end
    end
end

Tutorial1.unlockDoor = function(x, y, z)
    local sq = getSquare(x, y, z);
    for i=0, sq:getObjects():size() -1 do
        local obj = sq:getObjects():get(i);
        if instanceof(obj, "IsoDoor") then
            obj:setLockedByKey(false);
            obj:setLocked(false);
            return obj;
        end
    end
end

Tutorial1.addBarricade = function(x, y, z)
    local sq = getSquare(x, y, z)
    if sq then
        for i = 0, sq:getObjects():size()-1 do
            local o = sq:getObjects():get(i);
            if instanceof(o, "IsoWindow") then
                o:addBarricadesDebug(ZombRand(2,5), false);
                break;
            end
            if instanceof(o, "IsoDoor") then
                o:addRandomBarricades();
                break;
            end
        end
    end
end

Tutorial1.addMetalBarricade = function(x, y, z)
    local sq = getSquare(x, y, z)
    if sq then
        for i = 0, sq:getObjects():size()-1 do
            local o = sq:getObjects():get(i);
            if instanceof(o, "IsoWindow") then
                o:addBarricadesDebug(ZombRand(2,5), true);
                o:setPermaLocked(true);
                return o;
            end
        end
    end
end

Tutorial1.cratePositions = {{"lootingStuff", "counter", 157, 152, 0}};
Tutorial1.FillContainers = function()
    for k, v in ipairs(Tutorial1.cratePositions) do
        local type = v[1];
        local container = v[2];
        local x = v[3];
        local y = v[4];
        local z = v[5];
        local sq = getCell():getGridSquare(x, y, z);
        if sq ~= nil then
            local objs = sq:getObjects();
            for i = 0, objs:size()-1 do
                local o = objs:get(i);
                local c = o:getContainer();
                if c ~= nil and c:getType() == container then
                    c:emptyIt();
                    if type == "lootingStuff" then
                        Tutorial1.DeadMouseContainer = o;
                        local apple = c:AddItem("Base.DeadMouse");
                        apple:setAge(17);
                        Tutorial1.DeadMouse = apple
                        c:AddItem("Base.WaterBottleEmpty");
                    end
                    c:setExplored(true);
                end
            end
        end
    end
end

Tutorial1.SpawnZombies = function(count)

end

Tutorial1.Render = function()

end

Tutorial1.Tick = function()
    if getPlayer() == nil then return end;

    if Tutorial1.steps == nil or Tutorial1.steps:isEmpty() then return; end
    if JoypadState.players[1] then
        Tutorial1.joypad = true;
    end

    if Tutorial1.steps:get(0):isComplete() then
        Tutorial1.steps:get(0):finish();
        Tutorial1.steps:removeAt(0);

        if not Tutorial1.steps:isEmpty() then
            Tutorial1.steps:get(0):begin();
        end
    end
end

function Tutorial1.removeFences()
    for x=178, 187 do
        local sq = getSquare(x, 153, 0);
        Tutorial1.replaceFence(sq, true);
    end
    
    for y=143, 152 do
        local sq = getSquare(188, y, 0);
        Tutorial1.replaceFence(sq, false);
    end
end

function Tutorial1.replaceFence(sq, north)
--    local sprite = "walls_exterior_wooden_01_24"
--    if north then
--        sprite = "walls_exterior_wooden_01_25"
--    end
    if not sq then return end;
    for i=0, sq:getObjects():size()-1 do
        local obj = sq:getObjects():get(i);
        if obj:getType() == IsoObjectType.wall then
            local newFence = IsoThumpable.new(getCell(), sq, obj:getSprite():getName(), north, ISWoodenWall:new(obj:getSprite():getName(), obj:getSprite():getName(), nil));
            sq:AddTileObject(newFence);
            sq:RemoveTileObject(obj);
            return;
        end
--        if obj:getType() == IsoObjectType.doorW then
--            local newFence = IsoThumpable.new(getCell(), sq, "fencing_01_58", north, ISWoodenWall:new("fencing_01_58", "fencing_01_58", nil));
--            local newFence = IsoThumpable.new(getCell(), sq, sprite, north, ISWoodenWall:new(sprite, sprite, nil));
--            sq:AddTileObject(newFence);
--            sq:RemoveTileObject(obj);
--        end
    end
end
    
Tutorial1.name = "Tutorial1";
--Tutorial1.description = "Prepare for a short, sharp dose of Zomboid. Deadheads are approaching from every angle.\nYou're going to check out, and soon, but just how long can you resist the horde?\nReady that shotgun...";
Tutorial1.image = "media/lua/LastStand/Challenge1.png";
Tutorial1.world = "challengemaps/Tutorial";
Tutorial1.xcell = 0;
Tutorial1.ycell = 0;
Tutorial1.x = 157;
Tutorial1.y = 157;
Tutorial1.hourOfDay = 20;
--Tutorial1.cratePositions = { {"weapons3", "crate", 151, 152, 0},{"weapons2", "crate", 142, 148, 0}, {"weapons1", "crate", 147+3, 151+3, 1}, {"medicine", "crate", 156+3, 144+3, 1}, {"carpentry", "crate", 135, 179, 0}, {"carpentry", "crate", 157, 151, 0}, {"carpentry", "crate", 158, 151, 0}}
--Events.OnChallengeQuery.Add(Tutorial1.Add)
