#! /usr/bin/env ruby
require File.dirname(__FILE__) + '/lib/base'
require File.dirname(__FILE__) + '/lib/csv'

class SplashIdImporter < Importer

  TYPES = {
    "Web Logins" => [], # Needed even though we hardcode it below. See simplied_csv for details
    "Bank Accts" => ["Account #: ", "PIN: ", "Name: ", "Branch: ", "Phone #: "],
    "Birthdays" => ["Date: ", "", "", "", ""],
    "Calling Cards" => ["Access #: ", "PIN: ", "", "", ""],
    "Clothes Size" => ["Shirt Size: ", "Pant Size: ", "Shoe Size: ", "Dress Size: ", ""],
    "Combinations" => ["Code: ", "", "", "", ""],
    "Credit Cards" => ["Card #: ", "Expir. Date: ", "Name: ", "PIN: ", "Bank: "],
    "Email Accts" => ["Username: ", "Password: ", "POP3 Host: ", "SMTP Host: ", ""],
    "Emergency Info" => ["Phone #: ", "", "", "", ""],
    "Frequent Flyer" => ["Number: ", "Name: ", "Date: ", "", ""],
    "Identification" => ["Number: ", "Name: ", "Date: ", "", ""],
    "Insurance" => ["Policy #: ", "Group #:", "Insured: ", "Date: ", "Phone #: "],
    "Memberships" => ["Acct #: ", "Name: ", "Date: ", "", ""],
    "Phone Numbers" => ["Phone #: ", "", "", "", ""],
    "Prescriptions" => ["Rx #: ", "Name: ", "Doctor: ", "Pharmacy: ", "Phone #: "],
    "Serial Numbers" => ["Serial #: ", "Date: ", "Reseller: ", "", ""],
    "Vehicle Info" => ["License #: ", "VIN #: ", "", "", ""],
    "Voice Mail" => ["Access #: ", "PIN: ", "", "", ""],
  }

  UNFILED = ["", "", "", "", ""]
  
  def convert_commas(string)
    in_quotes, result = false, ""
    string.each_char { |c| 
      if in_quotes && c == ","
        result += "[COMMA]"
        next
      end
      
      result += c
      in_quotes = !in_quotes if c=="\"" 
    }
    return result
  end
  
  # SplashID allows multi-line notes to span multiple lines in the CSV file. I.e.:
  #
  #   > Web Logins,My long desc,dteare,password,http://agile.ws,,,,,,"December 19,2010","This 
  #   > is a very, 
  #   > very, very, long note",Personal
  #
  # We use the known type names ("Web Login", etc) as "line breaks" to collapse this into a single line with [NEWLINE] markers.
  # Note: a safer option might be comma-counting, but we cannot handle customized types anyway.
  def simplied_csv(orig)
    result, simplified_line = [], nil
    lines = orig.gsub("\r\n", "\n").gsub("\n\r", "\n").gsub("\r", "\n").split("\n")
    lines.each { |line|
      first_value = nil
      first_value = $1 if line =~ /^(.*?),/

      unless TYPES[first_value].nil?
        result << simplified_line unless simplified_line.nil?
        simplified_line = nil
      end
      
      if simplified_line
        simplified_line = "#{simplified_line}[NEWLINE]#{line}"
      else
        simplified_line = line
      end
    }
    result << simplified_line unless simplified_line.nil?
    return result.collect!{|line| convert_commas(line)}
  end
  
  def process_contents(contents)
    lines = simplied_csv(contents)
    lines.shift # Skip "SplashID Export File" header
    
    for line in lines do
      process_line(line)
    end
  end
  
  def process_line(line)
    items = CSV::parse_line(line)
    
  	if items.size < 9
  		add_error "Failed to parse line: #{line}"; 
  		return;
  	end
    
    for i in 0..items.size
      items[i] ||= ""
      items[i].gsub!(/\[COMMA\]/, ",")
    end

    type = items[0] || ""
    category = items[8] || ""
    description = items[1] || ""
    notes = (items[11] || "").gsub("\x0B", "\n").gsub(/\[COMMA\]/, ",").gsub(/\[NEWLINE\]/, "\n")
    
    item = nil
    
    if type == "Web Logins"
      item = WebForm.new
      item.name = category + "\\" + type + "\\" + description
      item.add_login(items[2], items[3])
      item.url = items[4]

      s = ""
      s += items[5] + "\n" if items[5] != ""
      s += items[6] + "\n" if items[6] != ""
      if notes != ""
        s += "-----\n" if s != ""
        s += notes
      end

      item.notes = s
      
    elsif type == "Credit Cards"
      item = AGCreditCard.new
      item.ccnum = items[2]
      item.title = items[4]
      item.pin = items[5]
      item.bank = items[6]
      item.notes = notes
      
    elsif type == "Bank Accts"
      item = AGBankAccountUS.new
      item.accountNo = items[2]
      notes = "PIN: #{items[3]}\n" + notes
      item.title = items[4]
      item.routingNo = items[5]
      item.branchPhone = items[6]
      item.notes = notes
      
    elsif type == "Serial Numbers"
      item = AGLicense.new
      item.title = items[4]
      item.reg_code = items[2]
      item.order_date = items[3]
      item.publisher_name = items[4]
      
      notes = items[5] + "\n" + notes if items[5] != "" 
      notes = items[6] + "\n" + notes if items[6] != "" 
      item.notes = notes
      
    else
      item = SecureNote.new
      item.name = category + "\\" + type + "\\" + description
      
      field_names = TYPES[type] || UNFILED
      
      s = ""
      s += "#{field_names[0]}#{items[2]}\n" if items[2] != ""
      s += "#{field_names[1]}#{items[3]}\n" if items[3] != ""
      s += "#{field_names[2]}#{items[4]}\n" if items[4] != ""
      s += "#{field_names[3]}#{items[5]}\n" if items[5] != ""
      s += "#{field_names[4]}#{items[6]}\n" if items[6] != ""
      if notes != ""
        s += "-----\n" if s != ""
        s += notes
      end

      item.notes = s
    end
    
    
    add_item item
  end
  
end

SplashIdImporter.new.run
