--[[
=============================================
Vexed v1.1 by Cancan

Adaptation of the Vexed game for Palm
created by James McCombe (http://vexed.sourceforge.net)

Email: cancangm (at) gmail (dot) com
=============================================
]]

--- Load scripts

dofile("common.lua")
dofile("vexed.lua")
dofile("themes.lua")

--- Current position of the cursor

posx = 0
posy = 0

--- Selected tile

isselected = false
selectx = 0
selecty = 0
selectvalue = 0
toanalyse = 0
tofall = 0

--- Levels

levels = {}
leveltitles = {}
levelscores = {}
levelsol = {}
levelundo = {}
undoposx = {}
undoposy = {}
currlevel = {}
levelcurr = 0
levelmax = 0
leveltitle = ""
levellines = 16
leveltop = 0
levelsteps = 0
levelremaining = 0
levelprev = 0

--- Preferences

vexedsound = 1
vexedlevel = 1
newvexedsound = 1
newvexedlevel = 1
prefselection = 0

themes = Selection:New()
themes:Init("themes", "", "Themes")
levelpacks = Selection:New()
levelpacks:Init("levels", ".ini", "Levels Packs")

dofile("settings.ini")
vexedsndyes = Sound.load("yes.wav")
vexedsnddone = Sound.load("done.wav")
vexedsndno = Sound.load("no.wav")

ReadTheme()
LoadLevelPack(levelcurr)
levelprev = levelcurr
if math.mod(levelcurr, levellines) == 0 then
  leveltop = levelcurr - levellines + 1
else
  leveltop = levelcurr - math.mod(levelcurr, levellines) + 1
end
InitLevel()

RenderLevel()
screen:waitVblankStart()
screen:flip()

if vexedsound == 1 then
  Music.playFile("./music.xm", true)
end

--- Functions

--- Save the Settings
function SaveSettings()
  file = io.open("settings.ini", "w")
  if file then
    file:write("themes.name = \"" .. themes.name .. "\"\n")
    file:write("levelpacks.name = \"" .. levelpacks.name .. "\"\n")
    file:write("levelcurr = " .. levelcurr .. "\n")
    file:write("vexedsound = " .. vexedsound .. "\n")
    file:write("vexedlevel = " .. vexedlevel .. "\n")
    file:close()
  end
end

function Selection:Load()
  if self.title  ==  "Themes"  then
    themes.name = self.table[self.current]
    ReadTheme() 
    RenderLevel()   
  else
    levelpacks.name = self.table[self.current]    
    levelcurr = 0
    LoadLevelPack(levelcurr)
    levelprev = levelcurr
    if math.mod(levelcurr, levellines) == 0 then
      leveltop = levelcurr - levellines + 1
    else
      leveltop = levelcurr - math.mod(levelcurr, levellines) + 1
    end
    InitLevel()
  end
  SaveSettings()
end

function drawSelection()

  boardsel:clear()
  boardsel:blit(0, 0, selection, 0, 0, selection:width(), selection:height(), true)

  boardsel:print(math.floor((selection:width() - 48) / 2), 4, "Levels", helpcolor)

  idx = leveltop
  while (idx <= levelmax) and (idx < (leveltop + levellines)) do
    if levelmax > 0 then
      if idx ~= 1 and levelscores[idx - 1] == 0 and vexedlevel == 1 then
        boardsel:print(5, 25 + ((idx - leveltop) * 12), "Complete previous one first", unselected)
      else
        if levelcurr == idx then
          boardsel:print(5, 25 + ((idx - leveltop) * 12), leveltitles[idx] .. " " .. levelscores[idx] .. "/" .. levelsol[idx], selected)
        else
          boardsel:print(5, 25 + ((idx - leveltop) * 12), leveltitles[idx] .. " " .. levelscores[idx] .. "/" .. levelsol[idx], unselected)
        end
      end
    end
    idx = idx + 1
  end

  screen:blit(math.floor((480 - selection:width()) / 2), math.floor((272 - selection:height()) / 2), boardsel, 0, 0, boardsel:width(), boardsel:height(), true);

end

function VexedPrefs()

  boardpref:clear()
  boardpref:blit(0, 0, prefs, 0, 0, prefs:width(), prefs:height(), true)

  boardpref:print(math.floor((prefs:width() - 70) / 2), 4, "Preferences",helpcolor)

  if prefselection == 0 then
    boardpref:print(9, 25, "Difficulty", selected)
    boardpref:print(9, 37, "Sounds", unselected)
  else
    boardpref:print(9, 25, "Difficulty", unselected)
    boardpref:print(9, 37, "Sounds",selected)
  end

  if newvexedsound == 0  then
    boardpref:print(160, 37, "Off", selected)
    boardpref:print(120, 37, "On", unselected)
  else
    boardpref:print(160, 37, "Off", unselected)
    boardpref:print(120, 37, "On", selected)
  end

  if newvexedlevel == 0  then
    boardpref:print(160, 25, "Easy", selected)
    boardpref:print(120, 25, "Hard", unselected)
  else
    boardpref:print(160, 25, "Easy", unselected)
    boardpref:print(120, 25, "Hard", selected)
  end

  screen:blit(math.floor((480 - prefs:width()) / 2), math.floor((272 - prefs:height()) / 2), boardpref, 0, 0, boardpref:width(), boardpref:height(), true);

end

--- Process the commands on the main screen

function KeyMain()
  if pad:square() then
    InitLevel()
  else
    if pad:r() then
      mode = 1
    end
    if pad:triangle() then
      mode = 2
    end
    if pad:l() then
      mode = 3
    end
    if pad:select() then
      newvexedsound = vexedsound
      newvexedlevel = vexedlevel
      prefselection = 0
      mode = 4
    end
    if pad:circle() then
      if levelsteps > 0 then
        for idx = 1, 80 do
          currlevel[idx] = levelundo[levelsteps][idx]
        end
        posx = undoposx[levelsteps]
        posy = undoposy[levelsteps]
        levelsteps = levelsteps - 1
        ifselected = false
        RenderLevel()
      end
    end
    if pad:cross()  then
      if ifselected then
        ifselected = false
      else
        if currlevel[((posy - 1) * 10) + posx] < 8 then
          ifselected = true
          selectx = posx
          selecty = posy
          selectvalue = currlevel[((posy - 1) * 10) + posx]
        end
      end
    else
      if ifselected then
        if pad:right() then
          if posx < 10 then
            TileMove(1)
          else
            if vexedsound == 1 then
              vexedsndno:play()
            end
          end
        elseif pad:left() then
          if posx > 1 then
            TileMove(-1)
          else
            if vexedsound == 1 then
              vexedsndno:play()
            end
          end
        end
      else
        if pad:up() then
          if posy > 1 then
              posy = posy - 1
           end
        elseif pad:down() then
          if posy < 8 then
            posy = posy + 1
          end
        elseif pad:right() then
          if posx < 10 then
            posx = posx + 1
          end
        elseif pad:left() then
          if posx > 1 then
            posx = posx - 1
          end
        end
      end
    end
  end
end

--- Process the commands on the Preferences screen

function KeyVexedPrefs()
  if pad:up() or pad:down() then
    if prefselection == 1 then
      prefselection = 0
    else
      prefselection = 1
    end

  elseif pad:right() or pad:left() then
    if prefselection == 1 then
      if newvexedsound == 0 then
        newvexedsound = 1
      else
        newvexedsound = 0
      end
    else
      if newvexedlevel == 0 then
        newvexedlevel = 1
      else
        newvexedlevel = 0
      end
    end

  elseif pad:cross() then
    mode = 0
    if vexedsound ~= newvexedsound then
      if vexedsound == 0 then
        Music.playFile("./music.xm", true)
      else
        Music.stop()
      end
    end
    vexedsound = newvexedsound
    vexedlevel = newvexedlevel
    SaveSettings()

  elseif pad:circle() then
    mode = 0
  end
end

--- Process the commands on the Level screen

function KeyLevel()
  if pad:up() then
    if levelcurr > leveltop then
      levelcurr = levelcurr - 1
    else
      if levelcurr > 1 then
        levelcurr = leveltop - 1
        leveltop = leveltop - levellines
      end
    end

  elseif pad:down() then
    if levelcurr ==  1 or vexedlevel == 0  or (vexedlevel == 1 and levelscores[levelcurr] > 0) then
      if levelcurr < levelmax then
        levelcurr = levelcurr + 1
        if levelcurr == (leveltop + levellines) then
          leveltop = levelcurr
        end
      end
    end

  elseif pad:right() then
    if (leveltop + levellines <= levelmax) and (vexedlevel == 0 or (levelscores[leveltop + levellines - 1] > 0 and vexedlevel == 1)) then
      leveltop = leveltop + levellines
      levelcurr = leveltop
    end

  elseif pad:left() then
    if leveltop ~= 1 then
      levelcurr = leveltop - 1
      leveltop = leveltop - levellines
    end

  elseif pad:cross() then
    if levelcurr == 1 or vexedlevel == 0 or (vexedlevel == 1  and levelscores[levelcurr - 1] > 0) then
      mode = 0
      SaveSettings()
      InitLevel()
      levelprev = levelcurr
    end

  elseif pad:circle() then
    levelcurr = levelprev
    if math.mod(levelcurr, levellines) == 0 then
      leveltop = levelcurr - levellines + 1
    else
      leveltop = levelcurr - math.mod(levelcurr, levellines) + 1
    end
    mode = 0

  end
end

--- Main processing

while goprg do

  --- Read controls

  pad = Controls.read()
  if pad:start() then
    goprg = false
  else
    if toanalyse == 1 then
      if tofall < 15
      then
        tofall = tofall + 1
      else
        AnalyseMap()
        tofall = 0
      end
      RenderTiles()
      screen:waitVblankStart()
      screen:flip()
    elseif pad ~= oldPad then
      if     mode == 0 then  KeyMain()
      elseif mode == 1 then  levelpacks:Event()
      elseif mode == 2 then  KeyLevel()
      elseif mode == 4 then  KeyVexedPrefs()
      else                   themes:Event()
      end
      oldPad = pad
 
    --- Update screen

      if     mode == 0 then  RenderTiles()
      elseif mode == 1 then  levelpacks:Draw()
      elseif mode == 2 then  drawSelection()
      elseif mode == 4 then  VexedPrefs()
      else                   themes:Draw()
      end

      screen:waitVblankStart()
      screen:flip()

    end
  end

end

if vexedsound == 1 then
  Music.stop()
end