-- CONTENTS
-- Init for dependencies and lua files
-- Chat Commands
-- minor bug fix functions

local S = minetest.get_translator("drwho_tardis")


drwho_tardis = { -- Global definition for the API functions and metadata
	VERSION = "1.2.0"
}
_drwho_tardis = {} -- Private API + storage

--
-- INIT FOR DEPENDENCIES AND LUA FILES
--

local MP = minetest.get_modpath("drwho_tardis")

dofile(MP .. "/init_data.lua") -- Initiate data such as interior rooms and crafting aliases
dofile(MP .. "/api.lua") -- The majority of API functions
dofile(MP .. "/tardis/console.lua") -- Formspecs + crafting. forms use local funtions so all in one file.
dofile(MP .. "/tardis/exterior_api.lua") -- Exterior api for registering exteriors 
dofile(MP .. "/tardis/default_exteriors.lua") -- All the exteriors that come with this mod
dofile(MP .. "/tardis/interior.lua") -- TARDIS Interior logic and node definitions

dofile(MP .. "/tools.lua") -- Dalekanium Tools 
dofile(MP .. "/craftitems.lua") -- All Craftitems
dofile(MP .. "/recipes.lua") -- Most Recipes
dofile(MP .. "/sonic.lua") -- Sonic Registration API and default sonic devices
dofile(MP .. "/armor.lua") -- Dalekanium Armor (if 3d_armor is enabled)
dofile(MP .. "/awards.lua") -- Various achievements (if awards is enabled)

-- Doctor Who Monsters (can be disabled in settings)
if minetest.settings:get_bool("drwho_tardis.enable_daleks") == false then
	return
else dofile(MP .. "/mobs/dalek.lua") end -- Daleks

if minetest.settings:get_bool("drwho_tardis.enable_cybermen") == false then
	return
else dofile(MP .. "/mobs/cybermen.lua") end -- Cybermen

-- Migration logic (tardis_new to drwho_tardis), 
-- aliases for items and nodes, modstorage is not migrated
dofile(MP .. "/migration.lua")


-- Subtitles for sound effects
if minetest.get_modpath("subtitles") then
	subtitles.register_description('Dalek_Voice', S('"You will obey the Daleks!"')) -- Too long to fit the screen
	subtitles.register_description('Shortened_Dalek_Voice', S('"You will be exterminated!"'))
	subtitles.register_description('Laser', S('Laser blast'))
	subtitles.register_description('sonic_sound', S('Sonic Screwdriver buzzing'))
	subtitles.register_description('tardis_sound', S('Tardis travelling sound'))
end

--Data (11) : in_pos, out_pos, y_dest, x_dest, z_dest, factor, look, r_pos, waypoint1, waypoint2, waypoint3, biome_pos, type, door_0_offset
-- This is going to be reworked in v1.3.0
local data = minetest.get_mod_storage()

--
-- CHAT COMMANDS
--

-- Print the detected gametype, for devs
minetest.register_chatcommand("tardis_gametype", {
	params = "",
	description = S("Prints the type of game (mtg, mcl, rp)"),
	privs = {debug = true},
	func = function(name)
		minetest.chat_send_player(name, "Game type is: ".._drwho_tardis.GAMETYPE)
	end
})

-- TEMPORARY - for devs
minetest.register_chatcommand("ext_list", {
	params = "",
	description = S("DEV COMMAND: temporary"),
	privs = {debug = true},
	func = function(name)
		local ext_list = drwho_tardis.get:exterior_list()
		for i, ext in ipairs(ext_list) do
			minetest.chat_send_player(name, minetest.serialize(ext))
			minetest.chat_send_player(name, minetest.serialize(ext.itemstring))
			if i >= 20 then
				break
			end
		end
	end
})

-- TEMPORARY - for devs
minetest.register_chatcommand("reset_ext", {
	params = "",
	description = S("DEV COMMAND: resets the players' Tardis exterior to blue Tardis"),
	privs = {debug = true},
	func = function(name)
		data:set_string(name.."look", "drwho_tardis:tardis")
		minetest.chat_send_player(name, S("Exterior look reset"))
	end
})

-- Fix interior doors
minetest.register_chatcommand("reset_in_doors", {
	params = "",
	description = S("Resets your Tardis interior doors and fixes their timers"),
	privs = {},
	func = function(name)
		local door_pos_table = minetest.deserialize(data:get_string(name.."door_pos_table"))
		if not door_pos_table or door_pos_table == "" or door_pos_table == {} then 
			local in_pos = minetest.deserialize(data:get_string(name.."in_pos"))
			door_pos_table = {}
			door_pos_table.door_0 = in_pos
			data:set_string(name.."door_pos_table", minetest.serialize(door_pos_table))
		end
		--minetest.log("init.lua line 116: "..minetest.serialize(door_pos_table))
		_drwho_tardis:init_interior_doors(name, door_pos_table)
		minetest.chat_send_player(name, S("interior doors are now reset"))
	end
})

-- TEMPORARY - as a dev I don't want to wait for power to regenerate
minetest.register_chatcommand("tardis_energy", {
	params = "",
	description = S("DEV COMMAND: maxes out Tardis energy"),
	privs = {debug = true},
	func = function(name)
		data:set_int(name.."power", 10)
		minetest.chat_send_player(name, "Tardis energy banks restored!")
	end
})

minetest.register_chatcommand("tardis_int", {
	params = "<type>",
	description = S("Change your Tardis interior type. Afterwards, remove everything from your Tardis and run /rebuild_tardis."),
	privs = {},
	func = function(name, param)
		local Params = string.split(param, ' ')
		if Params[1] == nil or Params[1] == '' then
			minetest.chat_send_player(name, "You must input the interior type after the command!")
		else
			data:set_string(name.."type", Params[1])
			minetest.chat_send_player(name, "Set interior type to "..Params[1])
			minetest.chat_send_player(name, "Now,  remove everything from your Tardis and run /rebuild_tardis. Make sure to be outside it though!")
		end
	end
})

-- Toggle 'respect_mavity'
minetest.register_chatcommand("tardis_mavity", {
	params = "",
	description = S("Toggles your Tardis's system for landing on ground instead of in the air or underground"),
	privs = {},
	func = function(name)
		local success, status = _drwho_tardis.toggle_mavity(name)
		minetest.chat_send_player(name, S(status))
	end
})

-- Summon TARDIS command 
minetest.register_chatcommand("summon_tardis", {
	params = "",
	description = S("Summons your Tardis to your location"),
	privs = {bring = true},
	func = function(name)
    if data:get_string(name.."in_pos") == "" then return false, S("Tardis not found") else
		local r_pos = minetest.deserialize(data:get_string(name.."r_pos"))
		local player = minetest.get_player_by_name(name)
		local select_pos = player:get_pos()
		if not r_pos then
			minetest.chat_send_player(name, S("You do not have a Tardis!")) 
		elseif r_pos.x+50 > select_pos.x and r_pos.x-50 < select_pos.x and r_pos.z+50 > select_pos.z and r_pos.z-50 < select_pos.z and r_pos.y+50 > select_pos.y and r_pos.y-50 < select_pos.y then minetest.chat_send_player(name, "Your Tardis can not be summoned here!") else
			if data:get_int(name.."power") < 3 then minetest.chat_send_player(name, "Not Enough Power In Tardis!") else
				local out_pos = minetest.deserialize(data:get_string(name.."out_pos"))
				local look = data:get_string(name.."look")
				minetest.set_node(out_pos, {name = "air"})
				out_pos.x = math.ceil(select_pos.x)
				out_pos.y = math.ceil(select_pos.y)
				out_pos.z = math.ceil(select_pos.z)					
				minetest.set_node(out_pos, {name=look})
				local ometa = minetest.get_meta(out_pos)
				ometa:set_string("id", name)
				data:set_string(name.."out_pos", minetest.serialize(out_pos))
				data:set_int(name.."power", data:get_string(name.."power")-3)
				local timer = minetest.get_node_timer(out_pos)
				timer:start(0.5)
				minetest.chat_send_player(name, S("Tardis Summoned"))
			end
		end
		--Unlock award:
		if minetest.get_modpath("awards") and _drwho_tardis.GAMETYPE=="mtg" then
			awards.unlock(name, "drwho_tardis:command_summon_tardis")
		end		
	end
	end
})

-- Rebuild TARDIS command
minetest.register_chatcommand("rebuild_tardis", {
	params = "",
	description = S("Rebuilds your Tardis interior. Do this when OUTSIDE of it. This will REMOVE anything else inside it!"),
	privs = {},
	func = function(name)
		-- This uses a private API function
		local success, errmsg, door_pos_table = _drwho_tardis:rebuild_tardis_interior(name)
		local _, __, pos = drwho_tardis.get:tardis_ext_position(name) -- public function
		local in_pos = minetest.deserialize(data:get_string(name.."in_pos"))
		data:set_string(name.."door_pos_table", minetest.serialize(door_pos_table))

		if success then 
			minetest.chat_send_player(name, S("Tardis interior rebuilt!"))
			minetest.chat_send_player(name, S("type: @1", data:get_string(name.."type")))
			minetest.chat_send_player(name, S("owner: @1", name))
			minetest.chat_send_player(name, S("exterior location: @1, @2, @3  [X,Y,Z]", pos.x, pos.y, pos.z))
			minetest.chat_send_player(name, S("interior door 0 (exit) location: @1, @2, @3  [X,Y,Z]", in_pos.x, in_pos.y, in_pos.z))
			if door_pos_table.door_1 then
				minetest.chat_send_player(name, S("interior door 1 location: @1, @2, @3  [X,Y,Z]", door_pos_table.door_1.x, door_pos_table.door_1.y, door_pos_table.door_1.z))
			end
			if door_pos_table.door_2 then
				minetest.chat_send_player(name, S("interior door 2 location: @1, @2, @3  [X,Y,Z]", door_pos_table.door_2.x, door_pos_table.door_2.y, door_pos_table.door_2.z))
			end
		else minetest.chat_send_player(name, S("Error message: @1", errmsg)) end
	end
})

-- Locate tardis command
-- This uses the public API function
-- Need to add a message if a player doesn't exist
minetest.register_chatcommand("locate_tardis", {
	params = "[<name>]",
	description = S("Locate your Tardis's exterior. Admins (server priv) can locate other player's Tardises."),
	privs = {}, 
	func = function(name, param)
		local Params = string.split(param, ' ')
		if Params[1] == nil or Params[1] == '' then
			local success, _, pos = drwho_tardis.get:tardis_ext_position(name)
			if success then
				minetest.chat_send_player(name, S("Your Tardis is at:  @1, @2, @3  [X,Y,Z]", pos.x, pos.y, pos.z))	
			else minetest.chat_send_player(name, S("You do not have a Tardis!")) end
		else -- Params[1] is another players name
			if minetest.check_player_privs(name, {server = true}) or minetest.check_player_privs(name, {debug = true}) then
				local success, _, pos = drwho_tardis.get:tardis_ext_position(Params[1])
				if success then
					minetest.chat_send_player(name, S("@1's Tardis is at:  @2, @3, @4  [X,Y,Z]", Params[1], pos.x, pos.y, pos.z))	
				else 
					minetest.chat_send_player(name, S("@1 does not have a Tardis!", Params[1])) 
				end
			else
				minetest.chat_send_player(name, S("You need admin privileges to locate other people's Tardises!"))
			end
		end
	end
})

minetest.register_on_player_receive_fields(function(player, formname, fields)
	if fields.teleport then
		local pos = minetest.string_to_pos(fields.teleport_x..","..fields.teleport_y..","..fields.teleport_z)
		player:set_pos(pos)
		player:set_hp(2)
	end
	if fields.sonic_send then
		local meta = player:get_meta()
		local pos = minetest.deserialize(meta:get_string("sonic_digiline"))
		digilines.receptor_send(pos, digilines.rules.default, fields.sonic_channel, fields.sonic_message)
	end
end)

--fix death stuff with vortex (removed, so probably doesn't matter anymore?)
minetest.register_on_dieplayer(function(player)
	local pmeta = player:get_meta()
	local id = pmeta:get_string("id")
	local r_pos = minetest.deserialize(data:get_string(id.."r_pos"))
	pmeta:set_string("vortex", "no")
	if r_pos then 
		local rmeta = minetest.get_meta(r_pos) 
		local style = rmeta:get_string("style") 
		_drwho_tardis.switch_time_rotor(id, "off")
	end
end)

--fix timers
minetest.register_lbm({
	name = "drwho_tardis:fix_timers",
	nodenames = {"group:tardis_in_door", "group:tardis_in_door_locked"},
	action = function(pos, node)
		local timer = minetest.get_node_timer(pos)
		timer:start(0.2)
	end
})

--aliases
minetest.register_alias("drwho_tardis:dalek_ingot", "drwho_tardis:dalekanium_ingot")
minetest.register_alias("drwho_tardis:tardis_blue", "drwho_tardis:tardis")
minetest.register_alias("drwho_tardis:tardis_empty", "drwho_tardis:tardis_invisible")
minetest.register_alias("drwho_tardis:tardis_leave", "drwho_tardis:tardis_leaves")
minetest.register_alias("drwho_tardis:tardis_cool", "drwho_tardis:tardis_classic")
minetest.register_alias("drwho_tardis:in_door_a", "drwho_tardis:in_door")