-- Intruder Alarm
--
-- Plays alarm locally at 1st person who is not the owner of the alarm
-- then must be manually reset by the owner to enable alarm again
-- Tells owner who invaded their privacy
-- use whatever license you care to use
-- Audio work done by Silicon Penguin
--
-- Alarm work done by daniel1 (inspired by mesecons player detector)
-- Needs a proper set of textures and not the ones I stole from mesecons
--
-- Suggested recipe at bottom
--

local alarm_scan_radius = 6
local S = minetest.get_translator("intruder_alarm")

-- after construct of alarm by placing... setup info
local function intruder_alarm_all_clear_after_place_node(pos, placer)
   local meta = minetest.get_meta(pos)
   meta:set_string("detectedname", "")
   meta:set_string("owner", placer:get_player_name() or "")
   meta:set_string("infotext", S("Intruder Alarm (owned by @1)", meta:get_string("owner")))
end

minetest.register_node("intruder_alarm:intruder_alarm", {
   description = 'Intruder Alarm',
   _doc_items_crafting = 'This tool is crafted in the Crystal Station.',
   _doc_items_longdesc = 'Sounds an alarm if any player other than the owner of the alarm comes within range. The owner will hear the alarm anywhere in the world...',
   _doc_items_usagehelp = "Right-click to disable/enable. Right-click triggered alarm to see who intruded upon your domain...",
   inventory_image = 'intruder_alarm_all_clear.png',
   tiles = {"intruder_alarm_top.png", "intruder_alarm_top.png", "intruder_alarm_all_clear.png", "intruder_alarm_all_clear.png", "intruder_alarm_all_clear.png", "intruder_alarm_all_clear.png"},
   paramtype = "light",
   is_ground_content = false,
   walkable = true,
   groups = {cracky=3},
   description="Intruder Alarm",
   on_construct = function(pos)
      local meta = minetest.get_meta(pos)
      meta:set_string('formspec', 'field[text;;${text}]')
   end,
   after_place_node = intruder_alarm_all_clear_after_place_node,
   on_receive_fields = function(pos, formname, fields, sender)
      local meta = minetest.get_meta(pos)
      if sender:get_player_name() == meta:get_string('owner') then
         if not fields.text then return end
         meta:set_string('text', fields.text)
         meta:set_string("infotext", S("Intruder Alarm (owned by @1)", meta:get_string("owner")))
      end
   end,
   on_punch = function(pos)
      minetest.swap_node(pos, {name = "intruder_alarm:intruder_alarm_disabled" })
   end,
   sounds = default.node_sound_stone_defaults(),
})

minetest.register_node("intruder_alarm:intruder_alarm_disabled", {
   tiles = {"intruder_alarm_top.png", "intruder_alarm_top.png", "intruder_alarm_disabled.png", "intruder_alarm_disabled.png", "intruder_alarm_disabled.png", "intruder_alarm_disabled.png"},
   paramtype = "light",
   is_ground_content = false,
   walkable = true,
   groups = {cracky=3,not_in_creative_inventory=1},
   drop = 'intruder_alarm:intruder_alarm',
   on_construct = intruder_alarm_make_formspec,
   on_punch = function(pos)
      local meta = minetest.get_meta(pos)
      minetest.swap_node(pos, {name = "intruder_alarm:intruder_alarm" })
      meta:set_string("infotext", S("Intruder Alarm (owned by @1)", meta:get_string("owner")))
   end,
   sounds = default.node_sound_stone_defaults(),
})

local function intruder_alarm_triggered_on_receive_fields(pos, formname, fields, sender)
   if minetest.is_protected(pos, sender:get_player_name()) then return end
   if not fields.detectedname then return end
   intruder_alarm_make_formspec(pos)
   -- reset detected name to empty
   local meta = minetest.get_meta(pos)
   meta:set_string("detectedname", "")
end

minetest.register_node("intruder_alarm:intruder_alarm_triggered", {
   tiles = {"intruder_alarm_top.png", "intruder_alarm_top.png", "intruder_alarm_triggered.png", "intruder_alarm_triggered.png", "intruder_alarm_triggered.png", "intruder_alarm_triggered.png"},
   paramtype = "light",
   is_ground_content = false,
   walkable = true,
   groups = {cracky=3,not_in_creative_inventory=1},
   drop = 'intruder_alarm:intruder_alarm',
   on_construct = intruder_alarm_make_formspec,
   on_receive_fields = intruder_alarm_triggered_on_receive_fields,
   on_punch = function(pos)
      minetest.swap_node(pos, {name = "intruder_alarm:intruder_alarm" })
   end,
   sounds = default.node_sound_stone_defaults(),
})

local function intruder_alarm_alert_owner(alarm_owner, location, looter)
   for _, player in ipairs(minetest.get_connected_players()) do
      local owner = minetest.get_player_by_name(alarm_owner)
      if player == owner then
         minetest.sound_play('alarm-sound', {to_player = alarm_owner, gain = .5}) -- as if off in the distance
         minetest.chat_send_player(alarm_owner, location..' alarm triggered by '..looter)
         return
      end
   end
end

minetest.register_abm({
   nodenames = {"intruder_alarm:intruder_alarm"},
   interval = 1,
   chance = 1,
   action = function(pos, node)
      local objs = minetest.get_objects_inside_radius(pos, alarm_scan_radius)
      local meta = minetest.get_meta(pos)
      local alarm_owner = meta:get_string("owner")
      local location = meta:get_string('text')
      for _, obj in pairs(objs) do
         local tmpname = obj:get_player_name()
         if tmpname ~= "" then
            if tmpname ~= alarm_owner then
               -- remember who was detected
               meta:set_string("detectedname", tmpname)
               minetest.swap_node(pos, {name = "intruder_alarm:intruder_alarm_triggered" })
               -- play alarm sound at node
               minetest.sound_play('alarm-sound', {pos = pos, gain = .75})
               -- play sound at owner
               intruder_alarm_alert_owner(alarm_owner, location, tmpname)
               meta:set_string('infotext', 'Alarm triggered by '..tmpname)
               return
            end
         end
      end
   end,
})

stations.dual_register_recipe('crystal_w', {
   input = {
      ['epic:thennium'] = 5,
      ['furniture:lock'] = 1,
      ['caverealms:glow_emerald'] = 1,
      ['caverealms:glow_mese'] = 1,
      ['caverealms:glow_ruby'] = 1,
   },
   output = 'intruder_alarm:intruder_alarm',
})
