#! /usr/bin/env python

# Copyright (C) 2008 by Sharif Oerton 
# sharif@oerton.net.au
#  
# This program is free software: you can redistribute it and/or 
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of 
# the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful, 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.*)

import socket
import pickle
import os
import sys

DIRNAME = os.path.expanduser("~/.grimoire/")
NUMRECORDS = DIRNAME + "numrecords"
S = "\n"

PORT = 1111

def init():
  if not os.path.isdir(DIRNAME):
    os.mkdir(DIRNAME)
  if os.path.exists(NUMRECORDS) == False:
    file = open(NUMRECORDS, 'w')
    file.write("0")

#Increment the number of records in the database
def incrementrecords():
  file = open(NUMRECORDS, "r")
  numrecords = file.read()
  file.close()
  numrecords = int(numrecords) + 1
  file = open(NUMRECORDS, 'w')
  file.write(str(numrecords))
  file.close()

#Decrement the number of records in the database
def decrementrecords():
  file = open(NUMRECORDS, "r+")
  numrecords = file.read()
  file.close()
  numrecords = int(numrecords) - 1
  file = open(NUMRECORDS, 'w')
  file.write(str(numrecords))
  file.close()

def getfilename(firstname, lastname):
  return DIRNAME + firstname + "_" + lastname

#Adds a record to the database
def add_record(firstname, lastname, email1, email2, add1, add2, city, state, postcode, country, homephone, workphone, fax, mobile):
  filename = getfilename(firstname, lastname)
  if os.path.exists(filename) == False:
    f = open(filename, 'w')
    f.write(firstname + S + lastname + S + email1 + S + email2 + S + add1 + S + add2 + S + city + S + state + S + postcode + S + country + S + homephone + S + workphone + S + fax + S + mobile)
    incrementrecords()
    return 0
  else:
    return -1

def get_record(firstname, lastname):
  f = open(getfilename(firstname, lastname), 'r')
  return f.read()

#Deletes a record from the database
def del_record(firstname, lastname):
  filename = getfilename(firstname, lastname)
  if os.path.exists(filename) == False:
    return -1
  else:
    os.remove(filename) 
    decrementrecords()
    return 0

#Modifies a record in the database
def mod_record(firstname, lastname, email1, email2, add1, add2, city, state, postcode, country, homephone, workphone, fax, mobile):
  filename = getfilename(firstname, lastname)
  file = open(filename, 'w')
  f.write(firstname + S + lastname + S + email1 + S + email2 + S + add1 + S + add2 + S + city + S + state + S + postcode + S + country + S + homephone + S + workphone + S + fax + S + mobile)
  return 0

#Lists all records in the database
def list_records():
  return os.listdir(DIRNAME)
 
#Sync with another machine, acting as a client
def sync(ip):
  client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  for rec in os.listdir(DIRNAME):
    client.sendto(rec, (ip, PORT))

  client.sendto("FINISHED", (ip, PORT))

  client.close()
  
  server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  server.bind(('', PORT))

  addrstoadd = pickle.loads(server.recvfrom(PORT)[0])

  server.close()
  
  client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

  for rec in addrstoadd:
    f = open(DIRNAME + rec, 'r')
    r = f.read()
    client.sendto(pickle.dumps((rec, r)), (ip, PORT))

  client.sendto("FINISHED", (ip, PORT))
  client.close()

#Sync with another machine, acting as a server
def serve(ip):
  addrstoadd = []
  server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  server.bind(('', PORT))

  t = "TEMP"

  while not t == "FINISHED":
    t = server.recvfrom(PORT)[0]
    if not t == "FINISHED":
      if t not in os.listdir(DIRNAME):
        addrstoadd.append(t)

  server.close()

  client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  client.sendto(pickle.dumps(addrstoadd), (ip, PORT))
  
  client.close()

  server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  server.bind(('', PORT))

  t = "TEMP"

  while not t == "FINISHED":
    t = server.recvfrom(PORT)[0]
    if not t == "FINISHED":
      f = open(DIRNAME + pickle.loads(t)[0], 'w')
      f.write(pickle.loads(t)[1])
      f.close()
      incrementrecords()

init()

def print_options():
  print '''Options are:\n
	-a: add new entry
	-r <firstname> <lastname>: remove entry
	-m <firstname> <lastname>: modify entry
	-g <firstname> <lastname>: retrieve entry
	-i: show all entries
	-s <IP address>: sync with another computer
	-l <IP address>: listen for syncing connections from a particular computer'''

if len(sys.argv) < 2:
  print_options()
  sys.exit()

if sys.argv[1] == "-a":
  fn = raw_input("Enter first name: ")
  ln = raw_input("Enter last name: ")
  email1 = raw_input("Enter email 1: ")
  email2 = raw_input("Enter email 2: ")
  add1 = raw_input("Enter address 1: ")
  add2 = raw_input("Enter address 2: ")
  city = raw_input("Enter city: ")
  state = raw_input("Enter state: ")
  postcode = raw_input("Enter postcode: ")
  country = raw_input("Enter country: ")
  homephone = raw_input("Enter home phone: ")
  workphone = raw_input("Enter work phone: ")
  fax = raw_input("Enter fax: ")
  mobile = raw_input("Enter mobile: ")

  add_record(fn, ln, email1, email2, add1, add2, city, state, postcode, country, homephone, workphone, fax, mobile)

elif sys.argv[1] == "-r":
  if len(sys.argv) == 4:
    del_record(sys.argv[2], sys.argv[3])
  else:
    print_options()

elif sys.argv[1] == "-m":
  if len(sys.argv) == 4:
    email1 = raw_input("Enter email 1: ")
    email2 = raw_input("Enter email 2: ")
    add1 = raw_input("Enter address 1: ")
    add2 = raw_input("Enter address 2: ")
    city = raw_input("Enter city: ")
    state = raw_input("Enter state: ")
    postcode = raw_input("Enter postcode: ")
    country = raw_input("Enter country: ")
    homephone = raw_input("Enter home phone: ")
    workphone = raw_input("Enter work phone: ")
    fax = raw_input("Enter fax: ")
    mobile = raw_input("Enter mobile: ")

    mod_record(sys.argv[2], sys.argv[3], email1, email2, add1, add2, city, state, postcode, country, homephone, workphone, fax, mobile)
  else:
    print_options()

elif sys.argv[1] == "-s":
  if len(sys.argv) == 3:
    print "Syncing..."
    sync(sys.argv[2])
    print "Syncing complete."
  else:
    print_options()

elif sys.argv[1] == "-l":
  if len(sys.argv) == 3:
    print "Listening..."
    serve(sys.argv[2])
    print "Transfer complete."
  else:
    print_options()

elif sys.argv[1] == "-g":
  if len(sys.argv) == 4:
    print get_record(sys.argv[2], sys.argv[3])
  else:
    print_options()
elif sys.argv[1] == "-i":
  for rec in list_records():
    print rec

else:
  print_options()

