--[[
=============================================
Contacts v0.8 by Cancan

Manage your contacts using vcf file structure (vCard) 
Virtual Danzeff keyboard 
Theme support

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

--- General variables

cwd = System.currentDirectory()
oldPad = nil
olddy = 0
olddx = 0
dy = 0
dx = 0
tickpad = 0
newchar = 0
goprg = true
idx = 0

--- Load scripts

dofile("danzeff.lua")
dofile("common.lua")
dofile("vcf.lua")
dofile("themes.lua")

--- Modes 0 = Main screen, 1 = Contact display, 2 = Theme selection, 3 = Contact field modification

mode = 0
oldmode = 0
vcardirty = 0

--- Fields

fieldpx  = {050, 050, 050, 050, 342, 050, 050, 242, 050, 242, 050, 050, 050, 050, 050, 240, 050, 050}
fieldpy  = {021, 035, 049, 063, 063, 077, 097, 097, 111, 111, 151, 163, 175, 187, 199, 199, 211, 231}
fieldmax = 18
fieldnumber = 0
field = ""
fieldpos = 0
contactedit = {}

--- Functions
function DisplayScreen()
  screen:clear()
  screen:blit(0, 0, board)
end

function SaveSettings()
  file = io.open("settings.ini", "w")
  if file then
    file:write("themes.name = \"" .. themes.name .. "\"\n")
    file:close()
  end
end

function Selection:Load()
  if self.title  ==  "Themes"  then
    themes.name = self.table[self.current]
    readTheme() 
    SaveSettings()
    mode = 0
  else
    mode = 1
    fieldnumber = 1
    contactedit = loadVCFFile(cwd .. "/vcf/" .. contacts.table[contacts.current] .. ".vcf")
  end
end

--- Initialization

themes = Selection:New()
themes:Init("themes", "", "Themes")
contacts = Selection:New()
contacts:Init("vcf", ".vcf", "Contacts")
keyboard = Danzeff:New()

dofile("settings.ini")

readTheme()
contacts:Draw()
screen:waitVblankStart()
screen:flip()

--- Functions

function UpdateField()

  if mode == 3 then
    screen:fillRect(fieldpx[fieldnumber] - 1, fieldpy[fieldnumber] - 2, (string.len(field) * 8) + 4, 10, selectedbg)
    screen:print(fieldpx[fieldnumber], fieldpy[fieldnumber], field, selected)
    screen:drawLine(fieldpx[fieldnumber] + (fieldpos * 8), 8 + fieldpy[fieldnumber], fieldpx[fieldnumber] + (fieldpos * 8) + 8, 8 + fieldpy[fieldnumber], cursorcolor)
    screen:drawLine(fieldpx[fieldnumber] + (fieldpos * 8), fieldpy[fieldnumber], fieldpx[fieldnumber] + (fieldpos * 8) + 8, fieldpy[fieldnumber], cursorcolor)
  else
    screen:fillRect(fieldpx[fieldnumber] - 1,fieldpy[fieldnumber] - 2, (string.len(contactedit[fieldnumber]) * 8) + 4, 10, selectedbg)
    screen:print(fieldpx[fieldnumber], fieldpy[fieldnumber], contactedit[fieldnumber], selected)
  end

end

function ContactDisplay()

  board:clear()

  board:blit(0, 0, background, 0, 0, background:width(), background:height(), false)

--- Display all the fields

  for idx = 1, fieldmax do
    if idx ~= fieldnumber then
      board:print(fieldpx[idx], fieldpy[idx], contactedit[idx], unselected)
    end
  end

  screen:blit(0, 0, board)

  UpdateField()
end

--- Process the commands when editing a field

function FieldEdit()

  --  Read Keyboard Input

  newchar = keyboard:Input(pad)

  --  Keyboard Input red

  if newchar == 4 or newchar == 3 or newchar == 10then
    mode = 1
    contactedit[fieldnumber] = field
    ContactDisplay()
  else
    DisplayScreen()
    if newchar == 1 then
        if fieldpos > 0 then fieldpos = fieldpos - 1 end
    elseif newchar == 2 then
        if fieldpos < string.len(field) then fieldpos = fieldpos + 1 end
    elseif newchar == 8 then
        if fieldpos > 0 then
          fieldend = string.sub(field, fieldpos + 1, string.len(field))
          fieldbeg = string.sub(field, 0, fieldpos - 1)
          field = fieldbeg .. fieldend
          fieldpos = fieldpos - 1
        end
    elseif newchar == 9 then
        if fieldpos < string.len(field) then
          fieldend = string.sub(field, fieldpos + 2, string.len(field))
          fieldbeg = string.sub(field, 0, fieldpos)
          field = fieldbeg .. fieldend
        end
    elseif newchar == 0 then
    else
        fieldend = string.sub(field, fieldpos + 1, string.len(field))
        fieldbeg = string.sub(field, 0, fieldpos)
        field = fieldbeg .. string.char(newchar) .. fieldend
        fieldpos = fieldpos + 1
    end
    UpdateField()
    keyboard:Display()
  end

  screen:waitVblankStart()
  screen:flip()
end

--- Process the commands on the main screen

function ContactListEvent()
  if pad:l() then
    mode = 2
  else
    if pad:square()  then
      contacts.max = contacts.max + 1
      table.insert(contacts.table, contacts.max, "")
      contacts.current = contacts.max
      contacts.previous = contacts.current
      if math.mod(contacts.previous, contacts.lines) == 0 then
        contacts.top = contacts.current - contacts.lines + 1
      else
        contacts.top = contacts.current - math.mod(contacts.current, contacts.lines) + 1
      end
      mode = 3 
      fieldnumber = 2
      for idx= 1, fieldmax do
        contactedit[idx] = ""
      end
      field = ""
      fieldpos = 0
      tickpad = 1
      oldmode = 0
      vcardirty = 1
      ContactDisplay()
    else
      if contacts.max > 0 then
        contacts:Event()
        if pad:circle() then
          os.remove(cwd .. "/vcf/" .. contacts.table[contacts.current] .. ".vcf")
            for idx = contacts.current, (contacts.max  - 1 ) do
              contacts.table[idx] = contacts.table[idx + 1]
            end 
            table.remove(contacts.table, contacts.max)
            contacts.max = contacts.max - 1
          if contacts.current > contacts.max then
            contacts.current = contacts.current - 1
            contacts.previous = contacts.current
            if contacts.current == 0 then
              contacts.top = 0
            else
              if contacts.top > contacts.current then
                contacts.top = contacts.top - contacts.lines
              end
            end
          end
        end
      end
    end
  end
end


function ContactEvent()
  if pad:cross() then
    mode = 3
    field = contactedit[fieldnumber]
    fieldpos = string.len(field)
    UpdateField()
    if fieldpy[fieldnumber] < 120 then
      keyboard:Init(330, 120)
    else
      keyboard:Init(330, 0)
    end
    tickpad = 1
    oldmode = 0
    vcardirty = 1
  elseif pad:circle()  then
    if contactedit[1] == "" then
      if contactedit[2] ~= "" then
        if contactedit[3] ~= "" then contactedit[1] = contactedit[3] .. " " .. contactedit[2]
        else  contactedit[1] = contactedit[2]
        end
      else contactedit[1] = contactedit[3]
      end
    end
    if contactedit[1] == "" then
      if contacts.table[contacts.current] ~= "" then
        os.remove(cwd .. "/vcf/" .. contacts.table[contacts.current] .. ".vcf")
      end
      for idx = contacts.current, (contacts.max  - 1 ) do
        contacts.table[idx] = contacts.table[idx + 1]
      end
      table.remove(contacts.table, contacts.max)
      contacts.max = contacts.max - 1
      if contacts.current > contacts.max then
        contacts.current = contacts.current - 1
        contacts.previous = contacts.current
        if contacts.curr == 0 then
          contacts.top = 0
        else
          if contacts.top > contacts.current then
            contacts.top = contacts.top - contacts.lines
          end
        end
      end
    else
      if contacts.table[contacts.current] ~= contactedit[1] then
        if contacts.table[contacts.current] ~= "" then
          os.remove(cwd .. "/vcf/" .. contacts.table[contacts.current] .. ".vcf")
        end
        contacts.table[contacts.current] = contactedit[1]
      end
      if vcardirty == 1 then
        saveVCFFile(cwd .. "/vcf/" .. contacts.table[contacts.current] .. ".vcf", contactedit)
        vcardirty = 0
      end
    end
    mode = 0
  elseif pad:down()  then
    fieldnumber = fieldnumber + 1
    if fieldnumber > fieldmax then
      fieldnumber = 1
    end
  elseif pad:up() then
    fieldnumber = fieldnumber - 1
    if fieldnumber < 1 then
      fieldnumber = fieldmax
    end
  end
end

--- Main processing

while goprg do

  --- Read controls

  pad = Controls.read()
  if mode ~= 3 then
    if pad ~= oldPad then
        oldPad = pad
        if mode == 0     then ContactListEvent()
        elseif mode == 2 then themes:Event()
                              themes:Draw()
        else                  ContactEvent()
        end

        if mode == 0 then
          contacts:Draw()
        elseif mode == 1 then
              ContactDisplay()
        elseif mode == 2 then
              themes:Draw()
        end

        screen:waitVblankStart()
        screen:flip()
    end
  else 
    dx = 2
    dy = 2

    if pad:analogX() < -42 then dx = 1 end
    if pad:analogX() > 42  then dx = 3 end
    if pad:analogY() < -42 then dy = 1 end
    if pad:analogY() > 42  then dy = 3 end

    if oldmode == 1 then
      if pad:buttons() ~= oldPad:buttons() or dy ~= olddy or dx ~= olddx then
        tickpad = 0 
      else
        tickpad = tickpad + 1
        if tickpad > 5 then tickpad = 0 end
      end
      if tickpad == 0 then
        oldPad = pad
        olddy = dy
        olddx = dx
        FieldEdit()
      else
        screen:waitVblankStart()
      end
    else
      oldPad = pad
      olddy = dy
      olddx = dx
      oldmode = 1
      screen:waitVblankStart()
    end
  end
end
