local wait = require("src/wait")

-- Define the exported object.
local skinHandler = {}

-- Initialize the animations page.
function skinHandler.init(main_page)
    skinHandler.animation_page = action_wheel:newPage()
    -- Add the ability to go back.
    skinHandler.animation_page:newAction()
        :title("Main Menu")
        :item("arrow")
        :onLeftClick(function()
            action_wheel:setPage(main_page)
        end)
    -- Return the page.
    return skinHandler.animation_page
end

-- Define the function used to add the skins to the specified page.
function skinHandler.add(object, skinPath)
    -- Register the skins.
    for skinName, skinDetails in pairs(object) do
        -- Create the ping for the skins.
        pings[skinName] = function()
            for ID, objectDetails in pairs(skinDetails.objects) do
                -- Prepare the skinpaths.
                local primaryTexturePath = processSkinPath(skinPath, skinName,
                    objectDetails.primaryTexture)
                -- Get the rendertype.
                local primaryRenderType = nil
                if (objectDetails.primaryMaterial) then
                    primaryRenderType = objectDetails.primaryMaterial
                end
                -- Apply the selected skin.
                objectDetails.modelPart:setPrimaryTexture("CUSTOM", textures[primaryTexturePath])
                objectDetails.modelPart:setPrimaryRenderType(primaryRenderType)

                -- Prepare the skinpaths.
                if (objectDetails.secondaryTexture) then
                    local secondaryTexturePath = processSkinPath(skinPath, skinName,
                        objectDetails.secondaryTexture)
                    -- Get the rendertype.
                    local secondaryRenderType = nil
                    if (objectDetails.secondaryMaterial) then
                        secondaryRenderType = objectDetails.secondaryMaterial
                    end
                    -- Apply the selected skin.
                    objectDetails.modelPart:setSecondaryTexture("CUSTOM",
                        textures[secondaryTexturePath])
                    objectDetails.modelPart:setSecondaryRenderType(primaryRenderType)
                else
                    -- Hide the entire layer.
                    objectDetails.modelPart:setSecondaryRenderType("NONE")
                end
            end

            -- Log the skin that's applied.
            skinHandler.appliedSkin = skinName;

            -- Save the skin that's being applied for later.
            config:save("applied_skin", skinName)
        end
        -- Add the action to the action_wheel.
        local action = skinHandler.animation_page:newAction()
            :title(skinName:gsub("_", " "):gsub("(%a)(%w*)",
                function(first, rest) return first:upper() .. rest:lower() end))
            :toggleTitle(skinName:gsub("_", " "):gsub("(%a)(%w*)",
                function(first, rest) return first:upper() .. rest:lower() end))
            :item(skinDetails.icon)
            :toggleItem(skinDetails.icon)
            :onLeftClick(pings[skinName])
    end

    -- System used to process our skin path.
    function processSkinPath(path, skinName, textureDetails)
        path = string.gsub(path, "{skinName}", skinName)
        path = string.gsub(path, "{object}", textureDetails)
        path = string.gsub(path, "{skinName}", skinName)
        path = string.gsub(path, "{object}", textureDetails)
        return path
    end
end

-- Define the function that will be used to load the skin indefinitely.
function skinHandler.load()
    -- Save the skin for the next time it loads.
    if host:isHost() then
        -- Load the existing config.
        local data = config:load("applied_skin") or "default"
        pings[data]()
    end
end

-- Run every 20 ticks.
function skinHandler.oneSecondTick()
    -- Apply the saved skin.
    skinHandler.load()
    -- Repeat the function.
    wait.schedule(20, skinHandler.oneSecondTick)
end

wait.schedule(20, skinHandler.oneSecondTick)

return skinHandler
