-- This file is part of thesixthroc's Pirate Ship softmod, licensed under GPLv3 and stored at https://github.com/ComfyFactory/ComfyFactorio and https://github.com/danielmartin0/ComfyFactorio-Pirates.

local Memory = require('maps.pirates.memory')
local Math = require('maps.pirates.math')
local Balance = require('maps.pirates.balance')
local Common = require('maps.pirates.common')
-- local CoreData = require 'maps.pirates.coredata'
-- local Utils = require 'maps.pirates.utils_local'
local _inspect = require('utils.inspect').inspect
--
-- local SurfacesCommon = require 'maps.pirates.surfaces.common'
local Raffle = require('utils.math.raffle')
local ShopCovered = require('maps.pirates.shop.covered')
local Classes = require('maps.pirates.roles.classes')
local Loot = require('maps.pirates.loot')

local Public = {}
Public.Data = require('maps.pirates.structures.quest_structures.market1.data')

function Public.create_step1_entities()
	local destination = Common.current_destination()
	local surface = game.surfaces[destination.surface_name]

	local quest_structure_data = destination.dynamic_data.quest_structure_data
	if not quest_structure_data then
		return
	end

	local position = quest_structure_data.position
	local hardcoded_data = Public.Data.step1

	quest_structure_data.blue_chest = surface.create_entity({
		name = 'blue-chest',
		position = Math.vector_sum(position, hardcoded_data.blue_chest),
		force = 'environment',
	})
	if quest_structure_data.blue_chest and quest_structure_data.blue_chest.valid then
		quest_structure_data.blue_chest.minable = false
		quest_structure_data.blue_chest.rotatable = false
		quest_structure_data.blue_chest.operable = false
		quest_structure_data.blue_chest.destructible = false
	end
	quest_structure_data.red_chest = surface.create_entity({
		name = 'red-chest',
		position = Math.vector_sum(position, hardcoded_data.red_chest),
		force = 'environment',
	})
	if quest_structure_data.red_chest and quest_structure_data.red_chest.valid then
		quest_structure_data.red_chest.minable = false
		quest_structure_data.red_chest.rotatable = false
		quest_structure_data.red_chest.operable = false
		quest_structure_data.red_chest.destructible = false
	end
	quest_structure_data.door_walls = {}
	for _, p in pairs(hardcoded_data.walls) do
		local e = surface.create_entity({
			name = 'stone-wall',
			position = Math.vector_sum(position, p),
			force = 'environment',
		})
		if e and e.valid then
			e.minable = false
			e.rotatable = false
			e.operable = false
			e.destructible = false
		end
		quest_structure_data.door_walls[#quest_structure_data.door_walls + 1] = e
	end
end

function Public.create_step2_entities()
	local memory = Memory.get_crew_memory()
	local destination = Common.current_destination()
	local surface = game.surfaces[destination.surface_name]

	local quest_structure_data = destination.dynamic_data.quest_structure_data
	if not quest_structure_data then
		return
	end

	local position = quest_structure_data.position
	local hardcoded_data = Public.Data.step2

	quest_structure_data.market = surface.create_entity({
		name = 'market',
		position = Math.vector_sum(position, hardcoded_data.market),
		force = memory.ancient_friendly_force_name,
	})
	if quest_structure_data.market and quest_structure_data.market.valid then
		quest_structure_data.market.minable = false
		quest_structure_data.market.rotatable = false
		quest_structure_data.market.destructible = false

		quest_structure_data.market.add_market_item({
			price = Balance.weapon_damage_upgrade_price(),
			offer = {
				type = 'nothing',
				effect_description = {
					'pirates.market_description_purchase_attack_upgrade',
					Balance.weapon_damage_upgrade_percentage(),
				},
			},
		})

		-- quest_structure_data.market.add_market_item{price={{'pistol', 1}}, offer={type = 'give-item', item = 'coin', count = Balance.coin_sell_amount}}
		-- quest_structure_data.market.add_market_item{price={{'burner-mining-drill', 1}}, offer={type = 'give-item', item = 'iron-plate', count = 9}}

		local how_many_coin_offers = 5
		if Balance.crew_scale() >= 1 then
			how_many_coin_offers = 6
		end

		-- Thinking of not having these offers available always (if it's bad design decision can always change it back)
		if Math.random(4) == 1 then
			quest_structure_data.market.add_market_item({
				price = { { name = 'pistol', count = 1 } },
				offer = { type = 'give-item', item = 'coin', count = Balance.coin_sell_amount },
			})
			how_many_coin_offers = how_many_coin_offers - 1
		end

		if Math.random(4) == 1 then
			quest_structure_data.market.add_market_item({
				price = { { name = 'burner-mining-drill', count = 1 } },
				offer = { type = 'give-item', item = 'iron-plate', count = 9 },
			})
			how_many_coin_offers = how_many_coin_offers - 1
		end

		local coin_offers = ShopCovered.market_generate_coin_offers(how_many_coin_offers)
		for _, o in pairs(coin_offers) do
			quest_structure_data.market.add_market_item(o)
		end

		if destination.static_params.class_for_sale then
			quest_structure_data.market.add_market_item({
				price = { { name = 'coin', count = Balance.class_cost(false) } },
				offer = {
					type = 'nothing',
					effect_description = {
						'pirates.market_description_purchase_class',
						Classes.display_form(destination.static_params.class_for_sale),
					},
				},
			})

			-- destination.dynamic_data.market_class_offer_rendering = rendering.draw_text{
			-- 	text = 'Class available: ' .. Classes.display_form(destination.static_params.class_for_sale),
			-- 	surface = surface,
			-- 	target = Utils.psum{special.position, hardcoded_data.market, {x = 1, y = -3.9}},
			-- 	color = CoreData.colors.renderingtext_green,
			-- 	scale = 2.5,
			-- 	font = 'default-game',
			-- 	alignment = 'center'
			-- }
		end
	end

	quest_structure_data.steel_chest = surface.create_entity({
		name = 'steel-chest',
		position = Math.vector_sum(position, hardcoded_data.steel_chest),
		force = memory.ancient_friendly_force_name,
	})
	if quest_structure_data.steel_chest and quest_structure_data.steel_chest.valid then
		quest_structure_data.steel_chest.minable = false
		quest_structure_data.steel_chest.rotatable = false
		quest_structure_data.steel_chest.destructible = false

		local inv = quest_structure_data.steel_chest.get_inventory(defines.inventory.chest)
		local loot = destination.dynamic_data.quest_structure_data.entry_price.raw_materials
		for j = 1, #loot do
			local l = loot[j]
			if l.count > 0 then
				inv.insert(l)
			end
		end
	end

	for _, w in pairs(quest_structure_data.door_walls) do
		w.destructible = true
		w.destroy()
	end

	quest_structure_data.wooden_chests = {}
	for k, p in ipairs(hardcoded_data.wooden_chests) do
		local e = surface.create_entity({
			name = 'wooden-chest',
			position = Math.vector_sum(position, p),
			force = memory.ancient_friendly_force_name,
		})
		if e and e.valid then
			e.minable = false
			e.rotatable = false
			e.destructible = false

			local inv = e.get_inventory(defines.inventory.chest)
			local loot = Loot.covered_wooden_chest_loot()
			if k == 1 then
				loot[1] = { name = 'coin', count = Loot.quest_structure_coin_loot() }
			end
			--@TODO: log this in coin stats
			for j = 1, #loot do
				local l = loot[j]
				inv.insert(l)
			end
		end
		quest_structure_data.wooden_chests[#quest_structure_data.wooden_chests + 1] = e
	end
end

Public.entry_price_data_raw = {
	--watch out that the raw_materials chest can only hold e.g. 4.8 iron-plates
	-- choose things that are easy to make at outposts
	-- if the prices are too high, players will accidentally throw too much in when they can't do it
	['iron-stick'] = {
		overall_weight = 1,
		min_param = 0,
		max_param = 0.4,
		shape = false,
		base_amount = 1500,
		raw_materials = { { name = 'iron-plate', count = 750 } },
	},
	['copper-cable'] = {
		overall_weight = 0.85,
		min_param = 0,
		max_param = 0.4,
		shape = false,
		base_amount = 1500,
		raw_materials = { { name = 'copper-plate', count = 750 } },
	},
	['small-electric-pole'] = {
		overall_weight = 1,
		min_param = 0,
		max_param = 0.3,
		shape = false,
		base_amount = 450,
		raw_materials = { { name = 'copper-plate', count = 900 } },
	},
	['assembling-machine-1'] = {
		overall_weight = 1,
		min_param = 0.1,
		max_param = 0.6,
		shape = false,
		base_amount = 80,
		raw_materials = { { name = 'iron-plate', count = 1760 }, { name = 'copper-plate', count = 360 } },
	},
	['burner-mining-drill'] = {
		overall_weight = 0.25,
		min_param = 0.1,
		max_param = 0.4,
		shape = false,
		base_amount = 150,
		raw_materials = { { name = 'iron-plate', count = 1350 } },
	},
	['burner-inserter'] = {
		overall_weight = 0.75,
		min_param = 0,
		max_param = 0.3,
		shape = false,
		base_amount = 300,
		raw_materials = { { name = 'iron-plate', count = 900 } },
	},
	['small-lamp'] = {
		overall_weight = 1,
		min_param = 0.05,
		max_param = 0.4,
		shape = false,
		base_amount = 300,
		raw_materials = { { name = 'iron-plate', count = 600 }, { name = 'copper-plate', count = 900 } },
	},
	['firearm-magazine'] = {
		overall_weight = 1,
		min_param = 0,
		max_param = 0.4,
		shape = false,
		base_amount = 700,
		raw_materials = { { name = 'iron-plate', count = 2800 } },
	},
	['constant-combinator'] = {
		overall_weight = 0.6,
		min_param = 0,
		max_param = 0.4,
		shape = false,
		base_amount = 276,
		raw_materials = { { name = 'iron-plate', count = 552 }, { name = 'copper-plate', count = 1518 } },
	},
	['stone-furnace'] = {
		overall_weight = 1,
		min_param = 0,
		max_param = 0.4,
		shape = false,
		base_amount = 250,
		raw_materials = { { name = 'stone', count = 1250 } },
	},
	['wooden-chest'] = {
		overall_weight = 0.5,
		min_param = 0,
		max_param = 0.4,
		shape = false,
		base_amount = 400,
		raw_materials = {},
	},
	['iron-chest'] = {
		overall_weight = 0.5,
		min_param = 0.1,
		max_param = 0.5,
		shape = false,
		base_amount = 250,
		raw_materials = { { name = 'iron-plate', count = 2000 } },
	},
	['steel-chest'] = {
		overall_weight = 0.5,
		min_param = 0.2,
		max_param = 1,
		shape = false,
		base_amount = 125,
		raw_materials = { { name = 'steel-plate', count = 1000 } },
	},
	['rail'] = {
		overall_weight = 1,
		min_param = 0.2,
		max_param = 1,
		shape = false,
		base_amount = 400,
		raw_materials = { { name = 'iron-plate', count = 1100 } },
	},
	['plastic-bar'] = {
		overall_weight = 1,
		min_param = 0.3,
		max_param = 1,
		shape = false,
		base_amount = 400,
		raw_materials = { { name = 'coal', count = 200 }, { name = 'petroleum-gas-barrel', count = 80 } },
	},
	['sulfur'] = {
		overall_weight = 1,
		min_param = 0.3,
		max_param = 1,
		shape = false,
		base_amount = 400,
		raw_materials = { { name = 'petroleum-gas-barrel', count = 120 } },
	},
	['electronic-circuit'] = {
		overall_weight = 1,
		min_param = 0.1,
		max_param = 0.5,
		shape = false,
		base_amount = 700,
		raw_materials = { { name = 'iron-plate', count = 700 }, { name = 'copper-plate', count = 1050 } },
	},
	['advanced-circuit'] = {
		overall_weight = 1,
		min_param = 0.4,
		max_param = 1,
		shape = false,
		base_amount = 180,
		raw_materials = {
			{ name = 'iron-plate', count = 360 },
			{ name = 'copper-plate', count = 900 },
			{ name = 'plastic-bar', count = 360 },
		},
	},
}

function Public.entry_price()
	local lambda = Math.clamp(0, 1, Math.sloped(Common.difficulty_scale(), 0.4) * Common.game_completion_progress())

	local item = Raffle.raffle_with_parameter(lambda, Public.entry_price_data_raw)

	if not item then
		item = Common.get_random_dictionary_entry(Public.entry_price_data_raw, true)
	end

	local base_count = Public.entry_price_data_raw[item].base_amount

	local factor = (0.9 + 0.2 * Math.random()) * Balance.quest_market_entry_price_scale()

	local count = Math.ceil(base_count * factor)

	local base_raw_materials = Public.entry_price_data_raw[item].raw_materials

	local raw_materials = {}
	for _, rm in pairs(base_raw_materials) do
		raw_materials[#raw_materials + 1] = { name = rm.name, count = Math.ceil(rm.count * factor) }
	end

	return {
		name = item,
		count = count,
		raw_materials = raw_materials,
	}
end

return Public
