require 'prb/prb'
require 'digest/md5'

module PRbSign
  class BadSign < RuntimeError; end

  class SignBook < PRb::PRbAttr
    def salt
      "SignBook"
    end

    def digest(name, phrase)
      Digest::MD5.hexdigest(name + salt + phrase.to_s)

#      Digest::MD5.new(name + salt + phrase.to_s).hexdigest

#      md5 = Digest::MD5.new(name.to_s)
#      md5.update(salt)
#      md5.update(phrase.to_s) if phrase
#      md5.hexdigest
    end

    def sign(name, phrase)
      name_digest = digest(name, nil)
      phrase_digest = digest(name, phrase)

      raise BadSign unless self[name_digest] == phrase_digest
      true
    end

    def set_sign(name, old_phrase, new_phrase)
      name_digest = digest(name, nil)
      old_digest = if old_phrase
		     digest(name, old_phrase)
		   else
		     nil
		   end
      new_digest = digest(name, new_phrase)
      transaction do
	raise BadSign unless self[name_digest] == old_digest
	self[name_digest] = new_digest
      end
      true
    end
  end

  class GuestBook < PRb::PRbObject
    def init
      self.signbook = SignBook.knew
      self.user = PRb::PRbAttr.knew
    end
    prb_attr :signbook, :user
    
    def get_user(name, phrase)
      transaction do
	self.signbook.sign(name, phrase)
	self.user[name]
      end
    end

    def add_user(name, phrase)
      transaction do
	self.signbook.set_sign(name, nil, phrase)
	guest = PRb::PRbAttr.knew
	guest[:name] = name
	self.user[name] = guest
	guest
      end
    end
  end
end
