local ecs = ...
local world = ecs.world
local w = world.w

local CONSTANT <const> = require "gameplay.interface.constant"
local FPS <const> = CONSTANT.FPS

local bgfx = require "bgfx"
local rhwi = import_package "ant.hwi"
local font = import_package "ant.font"
local irq = ecs.require "ant.render|renderqueue"
local iui = ecs.require "engine.system.ui_system"
local iroadnet = ecs.require "engine.roadnet"
local icanvas = ecs.require "engine.canvas"
local imountain = ecs.require "engine.mountain"
local iprototype = require "gameplay.interface.prototype"
local iguide = require "gameplay.interface.guide"
local ibackpack = require "gameplay.interface.backpack"
local iscience = require "gameplay.interface.science"
local gameplay_core = require "gameplay.core"
local saveload = ecs.require "saveload"
local global = require "global"
local iterrain  = ecs.require "terrain"
local imineral = ecs.require "mineral"
local init = ecs.require "init"
local game_settings = ecs.require "game_settings"
local settings_manager = import_package "vaststars.settings_manager"
local iwr = ecs.require "ant.render|viewport.window_resize"

local m = ecs.system "game_init_system"

bgfx.maxfps(FPS)
font.import "/pkg/vaststars.resources/ui/font/Alibaba-PuHuiTi-Regular.ttf"

local function get_lorry_ids()
    local l = {}
    for _, typeobject in pairs(iprototype.each_type("factory")) do
        local item = iprototype.queryByName(typeobject.lorry)
        l[item.id] = true
    end
    return l
end

local function init_game(template)
    local gameplay_world = gameplay_core.get_world()

    imineral.init(template.mineral)
    imountain:init(template.mountain)

    local w, h = settings_manager.get("window_size", "1280x720"):match("(%d+)x(%d+)")
    iwr.set_resolution_limits(w + 0, h + 0)

    rhwi.set_profie(settings_manager.get("debug", false))

    ibackpack.set_infinite_item(game_settings.infinite_item)
    ibackpack.set_lorry_ids(get_lorry_ids())

    icanvas.create("icon", template.canvas_icon ~= false and settings_manager.get("info", true) or false, 10)
    icanvas.create("pickup_icon", false, 10)

    if template.research_queue then
        gameplay_world:research_queue(template.research_queue)
    end

    if template.login_techs then
        gameplay_world:research_queue(template.login_techs)
        for _, tech in ipairs(template.login_techs) do
            local typeobject = iprototype.queryByName(tech)
            gameplay_world:research_progress(tech, typeobject.count)
            assert(gameplay_world:is_researched(tech))
        end
    end

    iguide.init(gameplay_world, template.guide)
    if next(template.guide) and game_settings.skip_guide then
        print("skip guide")
        for _, guide in ipairs(template.guide) do
            if next(guide.narrative_end.task) then
                for _, task in ipairs(guide.narrative_end.task) do
                    local typeobject = iprototype.queryByName(task)
                    gameplay_world:research_progress(task, typeobject.count)
                end
            end
        end
        gameplay_core.get_storage().guide_id = #template.guide + 1
    end
    iui.set_guide_progress(iguide.get_progress())
    iscience.update_tech_list(gameplay_world)

    for _, prefab in ipairs(template.init_instances) do
        world:create_instance {
            prefab = prefab
        }
    end

    for _, rml in ipairs(template.init_ui) do
        iui.open({rml = rml})
    end
end

local funcs = {}
funcs["nothing"] = function()
    world:create_instance {
        prefab = "/pkg/vaststars.resources/camera_default.prefab",
        on_ready = function(self)
            local eid = assert(self.tag["camera"][1])
            irq.set_camera_from_queuename("main_queue", eid)
        end
    }
end

funcs["terrain_only"] = function()
    iterrain.create()
    world:create_instance {
        prefab = "/pkg/vaststars.resources/camera_default.prefab",
        on_ready = function(self)
            local eid = assert(self.tag["camera"][1])
            irq.set_camera_from_queuename("main_queue", eid)
        end
    }
end

funcs["new_game"] = function(file)
    iterrain.create()
    iroadnet:create()

    saveload:restart(file)
    local template = ecs.require(("vaststars.prototype|%s"):format(file))
    for k, v in pairs(template.game_settings or {}) do
        game_settings[k] = v
    end

    -- replace the default camera
    world:create_instance {
        prefab = assert(template.camera),
        on_ready = function(self)
            local eid = assert(self.tag["camera"][1])
            irq.set_camera_from_queuename("main_queue", eid)
        end
    }

    init_game(template)
    world:import_feature "vaststars.gamerender|gameplay_update"
end

funcs["restore"] = function(path)
    iterrain.create()
    iroadnet:create()

    saveload:restore(path)
    local file = assert(gameplay_core.get_storage().game_template)
    local template = ecs.require(("vaststars.prototype|%s"):format(file))
    for k, v in pairs(template.game_settings or {}) do
        game_settings[k] = v
    end

    init_game(template)
    world:import_feature "vaststars.gamerender|gameplay_update"
end

function m:init()
    init()

    -- the light must be created in the frame before all entities are created
    world:create_instance {
        prefab = "/pkg/vaststars.resources/daynight_day.prefab"
    }
    world:create_instance {
        prefab = "/pkg/vaststars.resources/light.prefab"
    }
    world:create_instance {
        prefab = "/pkg/vaststars.resources/sky.prefab"
    }
end

function m:init_world()
    local args = global.startup_args
    local func = assert(funcs[args[1]])
    func(table.unpack(args, 2))
    global.startup_args = {}
end

function m:gameworld_prebuild()
    local world = gameplay_core.get_world()
    for e in world.ecs:select "REMOVED eid:in" do
        global.selected_buildings[e.eid] = nil
    end
end