--
-- adventure mode is for when we enter a node
--

function adventure_ctor (self)

   self.mode = nil -- 1 == read, 2 == menu
   self.node = nil -- the node we're adventuring in
   self.leave_flag = nil -- if set, then after latest "read" cycle we will leave
   self.leave_roadstream = nil -- what we leave to
   self.next_node = nil -- if set, then the n

   self.line_h = 20
   self.text_w = 10
   self.page_w = 400
   self.lines_per_page = 15
   self.lines_rate = 3.0 -- how many lines per second to unveil

   self.read_pages = nil -- what we're reading, if we are reading it
   self.cur_read_page = 1 -- what line we're on
   self.show_lines = 0 -- so we can unfold the lines gradually

   self.menu_options = nil -- our menu options
   self.cur_menu_option = 1 -- currently selected menu option, if menu
end

adventure = class (adventure_ctor)

function adventure:set_node (Node)

   self.leave_flag = nil
   self.leave_road = nil
   self.next_node = nil
   self.node = Node
   self:action ()
end

function adventure:set_next_node (Node)

   self.next_node = Node
end

function adventure:update (T)

   self.show_lines = self.show_lines + self.lines_rate * T
   if (self.show_lines > self.lines_per_page + 2) then self.show_lines = self.lines_per_page + 2
   end
end

function adventure:render (R)

   local RList = {}

   if (1 == self.mode) then

      local Page = self.read_pages[self.cur_read_page]
      table.insert (RList, self:render_page (R, Page))

      -- spacebar continue button
      table.insert (RList, R:rgba (0, 0, 1, 0.5))
      table.insert (RList, R:rect (0, 180, self.page_w / 2, 10))
      table.insert (RList, R:rgba (1, 1, 1, 1.0))
      table.insert (RList, R:centertext (0, 185, self.text_w, "Continue"))

   elseif (2 == self.mode) then

      local CurY = 180 - (sizeof (self.menu_options) - 1) * 20

      table.insert (RList, self:render_page (R, self.menu_pages[1]))

      -- render options
      for ID, Option in pairs (self.menu_options) do

         if (self.cur_menu_option == ID) then

            table.insert (RList, R:rgba (0, 0, 1, 0.5))
            table.insert (RList, R:rect (0, CurY, self.page_w / 2, 10))
         end

         -- text
         table.insert (RList, R:rgba (1, 1, 1, 1.0))
         table.insert (RList, R:centertext (0, CurY + 5, self.text_w, Option[2]))

         CurY = CurY + 20
      end
   end

   return R:union (RList)
end

function adventure:keypress (K)

   if (1 == self.mode) then

      if ("SPACE" == K or "RETURN" == K) then

         if (self.cur_read_page >= sizeof (self.read_pages)) then

            -- if the leave flag is set, then hit the road
            if (self.leave_flag) then cur_play:set_roadstream (self.leave_roadstream)
            elseif (self.next_node) then
               print "NEXT NODE"
               self:set_node (self.next_node)
            else self:menu ()
            end
         else

            self.cur_read_page = self.cur_read_page + 1
            self.show_lines = 0
         end
      end

   elseif (2 == self.mode) then

      if ("UP" == K) then self.cur_menu_option = clamp (self.cur_menu_option - 1, 1, sizeof (self.menu_options))
      elseif ("DOWN" == K) then self.cur_menu_option = clamp (self.cur_menu_option + 1, 1, sizeof (self.menu_options))
      elseif ("SPACE" == K or "RETURN" == K) then self:select ()
      end
   end
end

function adventure:action (Action)

   local T = self.node:action (Action)
   self.mode = 1
   self.read_pages = self:parse_text (T)
   self.show_lines = 0
   self.cur_read_page = 1
end

function adventure:menu ()

   local Prompt, Options = self.node:menu ()
   self.mode = 2
   self.cur_menu_option = 1
   self.menu_options = Options
   self.menu_pages = self:parse_text (Prompt)
   self.show_lines = 0
end

function adventure:select ()

   local Option = self.menu_options[self.cur_menu_option]
   self:action (Option[1])
end

function adventure:parse_text (T)

   -- split the text into readable lines
   local Lines = {}
   local Paras = T:split ("//");
   for ParaID, Para in pairs (Paras) do

      local Words = Para:split (" ")
      local CurLine = ""
      for WordID, Word in pairs (Words) do

         local NextLine = "     " .. Word
         if (CurLine ~= "") then NextLine = CurLine .. " " .. Word
         end

         local Len = text_len (self.text_w, NextLine)
         if (Len > self.page_w) then

            table.insert (Lines, CurLine)
            CurLine = Word
         else

            CurLine = NextLine
         end
      end

      -- blank lines at end of page
      if (CurLine ~= "") then table.insert (Lines, CurLine)
      end
      table.insert (Lines, "")
   end

   -- split into pages
   local Pages = {}
   local CurPage = {}
   for LineID, Line in pairs (Lines) do

      if (sizeof (CurPage) > self.lines_per_page or "     **" == Line) then

         table.insert (Pages, CurPage)
         CurPage = {}
         if ("     **" == Line) then Line = ""
         end
      end

      -- if the first line is blank, then skip it
      if (sizeof (CurPage) > 0 or "" ~= Line) then table.insert (CurPage, Line)
      end
   end
   if (sizeof (CurPage) > 0) then table.insert (Pages, CurPage)
   end

   return Pages
end

function adventure:render_page (R, Page)

   local RList = {}
   local CurY = -160
   table.insert (RList, R:rgba (.7, .7, .7, 1.0))
   for ID, Line in pairs (Page) do

      if (ID <= math.floor (self.show_lines)) then

         if (ID == math.floor (self.show_lines)) then

            -- alpha fade in bottom line
            local Alpha = self.show_lines - ID
            table.insert (RList, R:rgba (.7 * Alpha, .7 * Alpha, .7 * Alpha, 1.0))

         else

            table.insert (RList, R:rgba (.7, .7, .7, 1.0))
         end

         table.insert (RList, R:text (-self.page_w / 2, CurY, self.text_w, Line))
         CurY = CurY + self.line_h
      end
   end
   return R:union (RList)
end

function adventure:leave (Roadstream)

   -- if new road is specified, then leave towards that road; otherwise, return to previous road
   self.leave_flag = true
   self.leave_roadstream = Roadstream
end

