------------------------------------------------------------------------------
-- lm_timed.lua:
-- Lua timed map feature markers.
------------------------------------------------------------------------------

dofile('clua/lm_tmsg.lua')

TimedMarker = PortalDescriptor:new()
TimedMarker.__index = TimedMarker

function TimedMarker:_new()
  local marker = { }
  setmetatable(marker, self)
  self.__index = self
  return marker
end

function TimedMarker:new(pars)
  pars = pars or { }
  if not pars.msg then
    error("No messaging object provided (msg = nil)")
  end
  pars.high = pars.high or pars.low or pars.turns or 1
  pars.low  = pars.low or pars.high or pars.turns or 1
  local dur = crawl.random_range(pars.low, pars.high, pars.navg or 1)
  local feat = pars.floor or 'floor'
  local fnum = dgn.feature_number(feat)
  if fnum == dgn.feature_number('unseen') then
    error("Bad feature name: " .. feat)
  end

  local tmarker     = self:_new()
  tmarker.dur       = dur * 10
  tmarker.fnum      = fnum
  tmarker.feat      = feat
  tmarker.msg       = pars.msg
  tmarker.disappear = pars.disappear

  if pars.props then
    tmarker.props = pars.props
  end
  return tmarker
end

function TimedMarker:activate(marker, verbose)
  self.msg:init(self, marker, verbose)

  dgn.register_listener(dgn.dgn_event_type('turn'), marker)
  dgn.register_listener(dgn.dgn_event_type('player_climb'),
                        marker, marker:pos())
end

function TimedMarker:timeout(marker, verbose, affect_player)
  local x, y = marker:pos()

  if you.pos() == marker:pos() and you.taking_stairs() then
    if verbose then
      crawl.mpr( dgn.feature_desc_at(x, y, "The") .. " vanishes " ..
                "just as you enter it!")
      return
    end
  end

  if verbose then
    if you.see_grid(marker:pos()) then
      crawl.mpr( self.disappear or
                 dgn.feature_desc_at(x, y, "The") .. " disappears!")
    else
      crawl.mpr("The walls and floor vibrate strangely for a moment.")
    end
  end
  dgn.terrain_changed(x, y, self.fnum, affect_player, false)
  dgn.remove_listener(marker)
  dgn.remove_listener(marker, marker:pos())
  dgn.remove_marker(marker)
end

function TimedMarker:event(marker, ev)
  self.ticktype = self.ticktype or dgn.dgn_event_type('turn')
  self.stairtype = self.stairtype or dgn.dgn_event_type('player_climb')

  if ev:type() == self.stairtype then
    local mx, my = marker:pos()
    local ex, ey = ev:pos()
    if mx == ex and my == ey then
      self:timeout(marker, false, false)
    end
    return
  end

  if ev:type() ~= self.ticktype then
    return
  end
  self.dur = self.dur - ev:ticks()
  self.msg:event(self, marker, ev)
  if self.dur <= 0 then
    self:timeout(marker, true, true)
  end
end

function TimedMarker:describe(marker)
  return self.feat .. "/" .. tostring(self.dur)
end

function TimedMarker:read(marker, th)
  PortalDescriptor.read(self, marker, th)
  self.dur = file.unmarshall_number(th)
  self.fnum = file.unmarshall_number(th)
  self.feat = file.unmarshall_string(th)
  self.disappear = file.unmarshall_meta(th)
  self.msg  = file.unmarshall_fn(th)(th)
  setmetatable(self, TimedMarker)
  return self
end

function TimedMarker:write(marker, th)
  PortalDescriptor.write(self, marker, th)
  file.marshall(th, self.dur)
  file.marshall(th, self.fnum)
  file.marshall(th, self.feat)
  file.marshall_meta(th, self.disappear)
  file.marshall(th, self.msg.read)
  self.msg:write(th)
end

function timed_marker(pars)
  return TimedMarker:new(pars)
end
