require 'thread'
require 'md5'
require 'parsedate'
require 'pstore'
require 'singleton'

class Todo
  include Singleton

  class Item
    def initialize(text, owner, time, prio)
      @text = text
      @owner = owner
      @time = time
      @priority = prio
      md5 = MD5.new([text, owner, time, prio].inspect)
      @key =  md5.hexdigest[0,16]
    end
    attr_reader :key
    attr_accessor :text, :owner, :time, :priority

    def <=>(obj)
      cmp = obj.priority.to_i <=> @priority.to_i
      return cmp unless cmp == 0
      @time <=> obj.time
    end

    def to_hash
      {'key'=>@key, 
	'owner'=>@owner, 'time'=>@time, 'text'=>@text, 'priority'=>@priority}
    end
  end

  @@filename = 'todo.db'
  def self.filename=(fname)
    @@filename = fname
  end

  def initialize
    @mutex = Mutex.new
    @item = []
    @pstore = PStore.new(@@filename)
    load
  end
  attr_reader :item

  def list(who)
    @mutex.synchronize do
      @item.find_all do |item|
	item.owner == who
      end
    end
  end

  def fetch_hash(who)
    ary = list(who)
    ary.collect do |item|
      item.to_hash
    end
  end

  def add(text, owner, time, priority)
    @mutex.synchronize do
      @item.push(Item.new(text, owner, time, priority))
      @item.sort!
    end
    save
  end

  def remove(who, key)
    @mutex.synchronize do
      @item.delete_if do |item|
	item.owner == who and item.key == key
      end
    end
    save
  end

  private
  def load
    @mutex.synchronize do
      @pstore.transaction do |db|
	db['item'] = [] unless db.root?('item')
	@item = db['item']
      end
      @item = [] unless @item
    end
  end

  def save
    @mutex.synchronize do
      @pstore.transaction do |db|
	db['item'] = @item
	db.commit
      end
    end
  end
end

if __FILE__ == $0
  require 'drb/drb'

  front = Todo.instance
  DRb.start_service(ARGV.shift || 'druby://localhost:7984', front)
  puts DRb.uri
  gets
end
