-- CONTENTS
-- Init for dependencies and lua files
-- Special Item registrations and logic
--      e.g. sonic screwdriver, vortex manipulator



-- INIT FOR DEPENDENCIES AND LUA FILES

local MP = minetest.get_modpath("drwho_tardis")

dofile(MP .. "/exterior.lua") -- TARDIS Exterior logic and node definitions
dofile(MP .. "/interior.lua") -- TARDIS Interior logic and node definitions
dofile(MP .. "/console.lua") -- TARDIS Functions, Console logic and console node definitions
dofile(MP .. "/tools.lua") -- Dalekanium Tools 
dofile(MP .. "/craftitems.lua") -- All Craftitems
dofile(MP .. "/recipes.lua") -- Most Recipes
dofile(MP .. "/dalek.lua") -- Daleks

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

-- Dalekanium Armor (if 3d_armor is enabled)
if minetest.get_modpath("3d_armor") then
	dofile(MP .. "/armor.lua")
end

-- Various achievements (if awards is enabled)
if minetest.get_modpath("awards") then
	dofile(MP .. "/awards.lua")
end


-- Toolranks support
if minetest.get_modpath("toolranks") then

    minetest.override_item("drwho_tardis:sword_dalek", {
        description = toolranks.create_description("Dalekanium Sword", 0, 1),
        original_description = "Dalekanium Sword",
        after_use = toolranks.new_afteruse
    })
    minetest.override_item("drwho_tardis:pick_dalek", {
        description = toolranks.create_description("Dalekanium Pickaxe", 0, 1),
        original_description = "Dalekanium Pickaxe",
        after_use = toolranks.new_afteruse
    })
    minetest.override_item("drwho_tardis:axe_dalek", {
        description = toolranks.create_description("Dalekanium Axe", 0, 1),
        original_description = "Dalekanium Axe",
        after_use = toolranks.new_afteruse
    })
    minetest.override_item("drwho_tardis:shovel_dalek", {
        description = toolranks.create_description("Dalekanium Shovel", 0, 1),
        original_description = "Dalekanium Shovel",
        after_use = toolranks.new_afteruse
    })
end


-- Pickaxe-Tweaks support
if minetest.get_modpath("pick_axe_tweaks") then
	pick_axe_tweaks.register_pick_axes({"drwho_tardis:pick_dalek"})
end


--Data (11) : in_pos, out_pos, y_dest, x_dest, z_dest, factor, look, r_pos, waypoint1, waypoint2, waypoint3
data = minetest.get_mod_storage()



-- SPECIAL ITEM REGISTRATION AND LOGIC

--sonic screwdriver
local function get_formspec_digilines()
    return "size[10,10]"..
		"field[1,1;8,1;sonic_message;Message;]"..
		"field[1,3;8,1;sonic_channel;Channel;]"..
		"button_exit[1,6;3,3;sonic_send;Send]"
end
minetest.register_tool("drwho_tardis:sonic_screwdriver", {
	description = "Sonic Screwdriver",
	inventory_image = "sonic_screwdriver.png",
	stack_max=1,
	on_use = function(itemstack, player, pointed_thing)
	local pmeta = player:get_meta()
	local id = player:get_player_name()
	local imeta = itemstack:get_meta()
	imeta:set_string("interact", "no")
	if pointed_thing.type == "node" then
		local controls = player:get_player_control()
		local node = minetest.get_node(pointed_thing.under)
		local meta = minetest.get_meta(pointed_thing.under)
		local select_pos = pointed_thing.under
		local drop = minetest.get_node_drops(node, nil)
		if controls.sneak then 
			local r_pos = minetest.deserialize(data:get_string(id.."r_pos"))
			if 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(id, "Your Tardis can not be summoned here!") else
				if data:get_int(id.."power") < 3 then minetest.chat_send_player(id, "Not Enough Power In Tardis!") else
					local select_pos = pointed_thing.above
					local out_pos = minetest.deserialize(data:get_string(id.."out_pos"))
					local look = data:get_string(id.."look")
					minetest.set_node(out_pos, {name = "air"})
					out_pos.x = select_pos.x
					out_pos.y = select_pos.y
					out_pos.z = select_pos.z
						
					out_pos.y = out_pos.y+1
					minetest.set_node(out_pos, {name = "air"})
					out_pos.y = out_pos.y-1
					
					minetest.set_node(out_pos, {name=look})
					local ometa = minetest.get_meta(out_pos)
					ometa:set_string("id", id)
					data:set_string(id.."out_pos", minetest.serialize(out_pos))
					data:set_int(id.."power", data:get_string(id.."power")-3)
					local timer = minetest.get_node_timer(out_pos)
					timer:start(0.5)
					minetest.chat_send_player(id, "Tardis Summoned")
				end
			end
		else
			if id == meta:get_string("id") then
				if minetest.get_item_group(node.name, "tardis") == 1 then
					local look = data:get_string(id.."look")
					minetest.set_node(select_pos, {name = look.."_locked"})
					local ometa = minetest.get_meta(select_pos)
					ometa:set_string("id", id)
					minetest.chat_send_player(id, "Tardis Locked")
				end
				if minetest.get_item_group(node.name, "tardis_locked") == 1 then
					local look = data:get_string(id.."look")
					minetest.set_node(select_pos, {name = look})
					local timer = minetest.get_node_timer(select_pos)
					timer:start(0.2)
					local ometa = minetest.get_meta(select_pos)
					ometa:set_string("id", id)
					minetest.chat_send_player(id, "Tardis Unlocked")
				end
			end
			if node.name == "doors:door_steel_a" or node.name == "doors:door_steel_c" then
				doors.door_toggle(select_pos, nil, nil)
			end
			if node.name == "doors:trapdoor_steel" or node.name == "doors:trapdoor_steel_open" then
				doors.trapdoor_toggle(select_pos, nil, nil)
			end
			if node.name == "default:glass" then
				minetest.set_node(select_pos, {name = "default:obsidian_glass"})
			end
			if node.name == "default:dirt" then
				minetest.set_node(select_pos, {name = "default:dirt_with_grass"})
			end
			if node.name == "default:sand" then
				minetest.set_node(select_pos, {name = "default:silver_sand"})
			end
			if node.name == "default:obsidian" then
				minetest.set_node(select_pos, {name = "default:lava_source"} )
			end
			if minetest.get_item_group(node.name, "mesecon_conductor_craftable") == 1 then
				if mesecon.is_conductor_on(node) then
					mesecon.turnoff(select_pos, {0, 0, 0})
				else
					mesecon.turnon(select_pos, {0, 0, 0})
				end
			end
			if drop[1] == "digilines:wire_std_00000000" then
				local meta = player:get_meta()
				meta:set_string("sonic_digiline", minetest.serialize(select_pos))
				minetest.show_formspec(player:get_player_name(), "drwho_tardis:digilines_formspec", get_formspec_digilines() )
			end
		end
	end
	if pointed_thing.type == "object" then
		local controls = player:get_player_control()
		local obj = pointed_thing.ref
		if controls.sneak then 
			local vpos = obj:get_pos()
			local pos = player:get_pos()
			if obj:is_player() then 
			obj:add_player_velocity({ x = 5*(vpos.x - pos.x), y = 5*(vpos.y - pos.y), z = 5*(vpos.z - pos.z)})
			else
			obj:add_velocity({ x = 5*(vpos.x - pos.x), y = 5*(vpos.y - pos.y), z = 5*(vpos.z - pos.z)})
			end
		else 
			minetest.chat_send_player(id, "Scanned subject had " .. obj:get_hp()/2 .. " hearts")
		end
	end
	minetest.sound_play("sonic_sound", { max_hear_distance = 10})
	itemstack:set_wear(itemstack:get_wear() + 500) return itemstack
end -- End Sonic Screwdriver
})


-- gauntlet of rassilon
minetest.register_tool("drwho_tardis:rassilon_gauntlet", {
	description = "Gaunlet of Rassilon",
	inventory_image = "gauntlet_rassilon.png",
	stack_max=1,
	on_use = function(itemstack, player, pointed_thing)
		if pointed_thing.type == "object" then
			local obj = pointed_thing.ref
			obj:punch(player, nil, {full_punch_interval = 0.1, damage_groups = {fleshy=500}}, nil)
			itemstack:set_wear(itemstack:get_wear() + 4500) return itemstack
		end
	end
})


-- vortex manipulator
local function get_formspec_vortex()
    return "size[10,10]"..
		"field[1,1;8,1;teleport_x;X-Cord;0]"..
		"field[1,3;8,1;teleport_y;Y-Cord;0]"..
		"field[1,5;8,1;teleport_z;Z-Cord;0]"..
		"image_button_exit[1,6.5;3,3;dial_1.png;teleport; ;false;false;dial_2.png]"
end
minetest.register_tool("drwho_tardis:vortex_manipulator", {
	description = "Vortex Manipulator",
	inventory_image = "vortex_manipulator.png",
	stack_max=1,
	on_use = function(itemstack, player, pointed_thing)
		minetest.show_formspec(player:get_player_name(), "drwho_tardis:vortex_formspec", get_formspec_vortex() )
		itemstack:set_wear(itemstack:get_wear() + 3000) return itemstack
	end
})


-- TARDIS Monitor Screen
local function get_formspec_screen(power, posx, posy, posz, desx, desy, desz, block, id)
	local power = "Tardis Energy Banks: " .. power
	local cur = "Current Position: " .. posx .. ", " .. posy .. ", " .. posz
	local dest = "Destination: " .. desx .. ", " .. desy .. ", " .. desz
	local block = block
	local id = "Tardis Owner: " .. id
    return "size[10,10]"..
		"label[1,1;"..minetest.formspec_escape(power).."]"..
		"label[1,2.5;"..minetest.formspec_escape(cur).."]"..
		"label[1,4;"..minetest.formspec_escape(dest).."]"..
		"label[1,5.5;Block Tardis Is On: ]"..
		"item_image[3,5;2,2;"..minetest.formspec_escape(block).."]"..
		"label[1,7;"..minetest.formspec_escape(id).."]"
end
minetest.register_node("drwho_tardis:monitor", {
		description = "Tardis Monitor",
		tiles = {"tardis_side_1.png", "tardis_side_1.png", "tardis_side_1.png", "tardis_side_1.png", "tardis_monitor_screen.png", "tardis_side_1.png"},
		drawtype = "nodebox",
		node_box = {
			type = "fixed",
			fixed = {
				{ -0.5, -0.4, 0.1, 0.5,  0.4, 0 },
				{ 0.1, 0.1, 0, -0.1, -0.1, -0.5},
			},
		},
		groups = {cracky = 3},
		after_place_node = function(pos, placer, itemstack, pointed_thing)
			local pmeta = placer:get_meta()
			local id = pmeta:get_string("id")
			local r_pos = minetest.deserialize(data:get_string(id.."r_pos"))
			if not r_pos then r_pos = placer:get_pos() end
			if r_pos.x+50 > pos.x and r_pos.x-50 < pos.x and r_pos.z+50 > pos.z and r_pos.z-50 < pos.z and r_pos.y+50 > pos.y and r_pos.y-50 < pos.y then
				local meta = minetest.get_meta(pos)
				local out_pos = minetest.deserialize(data:get_string(id.."out_pos"))
				meta:set_string("id", id)
		
				out_pos.y = out_pos.y-1
				local node = minetest.get_node(out_pos)
				if node.name == "ignore" then
					minetest.get_voxel_manip():read_from_map(out_pos, out_pos)
					local node = minetest.get_node(out_pos)
				end
				out_pos.y = out_pos.y+1
		
				meta:set_string("formspec", get_formspec_screen(data:get_int(id.."power"), out_pos.x, out_pos.y, out_pos.z, data:get_int(id.."x_dest"), data:get_int(id.."y_dest"), data:get_int(id.."z_dest"), node.name, id ))
			else minetest.dig_node(pos) end
		end,
		on_rightclick = function(pos)
			local meta = minetest.get_meta(pos)
			local id = meta:get_string("id")
			local out_pos = minetest.deserialize(data:get_string(id.."out_pos"))
		
			out_pos.y = out_pos.y-1
			local node = minetest.get_node(out_pos)
			if node.name == "ignore" then
				minetest.get_voxel_manip():read_from_map(out_pos, out_pos)
				local node = minetest.get_node(out_pos)
			end
			out_pos.y = out_pos.y+1
		
			meta:set_string("formspec", get_formspec_screen(data:get_int(id.."power"), out_pos.x, out_pos.y, out_pos.z, data:get_int(id.."x_dest"), data:get_int(id.."y_dest"), data:get_int(id.."z_dest"), node.name, id ))
		end -- end TARDIS Monitor
})


-- gallifreyan lab
local function get_formspec_lab()
	if minetest.get_modpath("mcl_core") then
		return "size[10,10]"..
		"image[4.5,2;1,1;arrow_icon.png]"..
		"list[current_name;fuel;2,2;1,1;1]"..
		"list[current_name;dest;7,2;1,1;1]"..
		"list[current_player;main;1,5;8,4;]"
    else 
		return "size[10,10]"..
		"image[4.5,2;1,1;arrow_icon.png]"..
		"list[context;fuel;2,2;1,1;1]"..
		"list[context;dest;7,2;1,1;1]"..
		"list[current_player;main;1,5;8,4;]"
	end
end
local function lab_recipe(item,result,pos, player)
	local meta = minetest.get_meta(pos)
	local inv = meta:get_inventory()
	if inv:contains_item("fuel", item) == true and inv:is_empty("dest") then
		inv:remove_item("fuel",item)
		local fuel_s = inv:get_stack("fuel", 2)
		inv:set_stack("fuel", 2, fuel_s)
		inv:set_stack("dest", 2, result)
		player:set_hp(player:get_hp()-4)
	end
end
local function lab_crafting(pos, player)
	lab_recipe("default:diamondblock","drwho_tardis:spacetime",pos, player)
	lab_recipe("default:mese_crystal","drwho_tardis:arton_crystal",pos, player)
	lab_recipe("default:diamond","drwho_tardis:azbantium_shard",pos, player)
	lab_recipe("default:mese","default:diamond",pos, player)
	lab_recipe("default:copper_ingot","default:steel_ingot",pos, player)
	lab_recipe("default:coal_lump","default:tin_lump 2",pos, player)
	lab_recipe("default:steelblock","default:mese_crystal 3",pos, player)
	lab_recipe("default:dirt","default:coal_lump",pos, player)
end
minetest.register_node("drwho_tardis:lab", {
		description = "Gallifreyan Lab",
		tiles = {"tardis_lab.png"},
		groups = {cracky = 3},
		on_construct = function(pos, node)
			local meta = minetest.get_meta(pos)
			local inv = meta:get_inventory()
			inv:set_size("fuel", 2*1)
			inv:set_size("dest", 2*1)
			formspec = get_formspec_lab()
			meta:set_string("formspec", formspec)
		end,
		on_metadata_inventory_put = function(pos, listname, index, stack, player)
			lab_crafting(pos, player)
		end,
		on_metadata_inventory_take = function(pos, listname, index, stack, player)
			lab_crafting(pos, player)
		end -- Gallifreyan Lab
})


-- gallifreyan chest
local function get_formspec_chest()
    return "size[24,15]"..
		"list[context;main;0,0.5;24,10;]"..
		"list[current_player;main;8,10.5;8,4;]"
end
minetest.register_node("drwho_tardis:chest", {
		description = "Gallifreyan Chest",
		tiles = {"tardis_chest_top.png", "tardis_chest_top.png", "tardis_chest_side.png", "tardis_chest_side.png", "tardis_chest_side.png", "tardis_chest_side.png"},
		groups = {cracky = 3},
		after_place_node = function(pos, placer, itemstack, pointed_thing)
			local meta = minetest.get_meta(pos)
			local inv = meta:get_inventory()
			meta:set_string("owner", placer:get_player_name())
			meta:set_string("infotext", "Chest owned by " .. placer:get_player_name())
			meta:set_string("formspec", get_formspec_chest())
			inv:set_size("main", 24*10) -- VERY large
		end,
		on_rightclick = function(pos, node, clicker, itemstack) 
			local meta = minetest.get_meta(pos)
			if clicker:get_player_name() == meta:get_string("owner") then meta:set_string("formspec", get_formspec_chest(pos)) else meta:set_string("formspec", "") end
		end -- gallifreyan chest
})

-- Summon TARDIS command
minetest.register_chatcommand("summon_tardis", {
	params = "",
	description = "Summons your Tardis to your location",
	privs = {bring = true},
	func = function(name)
    if data:get_string(name.."in_pos") == "" then return false, "tardis not found" else
		local player = minetest.get_player_by_name(name)
		local select_pos = player:get_pos()
		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))
		local timer = minetest.get_node_timer(out_pos)
		timer:start(0.5)
		--Unlock award:
		if minetest.get_modnames("awards") then
			awards.unlock(name, "drwho_tardis:command_summon_tardis")
		end
		minetest.chat_send_player(name, "Tardis Summoned")
		
	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
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") 
		minetest.swap_node(r_pos, {name = "drwho_tardis:rotor"..style }) 
	end
end)

--fix timers
minetest.register_lbm({
	name = "drwho_tardis:fix_timers",
	nodenames = {"drwho_tardis:in_door"},
	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")

-- aliases for mineclone_core
if minetest.get_modpath("mcl_core") then
	minetest.register_alias("default:steel_ingot", "mcl_core:iron_ingot")
	minetest.register_alias("default:copper_ingot", "mcl_nether:quartz")
	minetest.register_alias("default:tin_ingot", "mcl_core:iron_ingot")
	minetest.register_alias("default:steelblock", "mcl_core:ironblock")
	minetest.register_alias("default:tinblock", "mcl_core:ironblock")
	minetest.register_alias("default:gold_ingot", "mcl_core:gold_ingot")
	minetest.register_alias("default:goldblock", "mcl_core:goldblock")
	minetest.register_alias("default:obsidian", "mcl_core:obsidian")
	minetest.register_alias("default:glass", "mcl_core:glass")
	minetest.register_alias("default:mese_crystal", "mesecons:wire_00000000_off")
	minetest.register_alias("default:mese", "mesecons_torch:redstoneblock")
	minetest.register_alias("default:diamond", "mcl_core:diamond")
	minetest.register_alias("default:diamondblock", "mcl_core:diamondblock")
	minetest.register_alias("default:stick", "mcl_core:stick")
	minetest.register_alias("default:cactus", "mcl_flowers:tulip_orange")
	minetest.register_alias("default:dry_grass_1", "mcl_flowers:tulip_white")
	minetest.register_alias("default:junglegrass", "mcl_flowers:allium")
	minetest.register_alias("default:obsidian_block", "mcl_flowers:peony")
	minetest.register_alias("default:grass_1", "mcl_flowers:poppy")
	minetest.register_alias("default:bronzeblock", "mcl_flowers:sunflower") -- WHY is bronzeblock a sunflower??
	minetest.register_alias("default:permafrost", "mcl_flowers:dandelion")
	minetest.register_alias("default:silver_sandstone_block", "mcl_flowers:azure_bluet")
end