require 'yaml'
require 'fileutils'

require 'og/store'

module Og

# A Store that saves the object on the Filesystem.
# An extension of the Memory store.

class FilesysStore < Store

  # :section: Store methods.

  def self.dir(name)
    "#{name}_db"
  end

  def self.create(options)
    name = dir(options[:name])
    FileUtils.mkdir_p(name)
  rescue 
    Logger.error "Cannot create '#{name}'"
  end
  
  def self.destroy(options)
    name = dir(options[:name])
    FileUtils.rm_rf(name)
  rescue 
    Logger.error "Cannot destroy '#{name}'"
  end

  # Initialize a connection to this store.

  def initialize(options)
    super

    @base_dir = self.class.dir(options[:name])
  
    unless File.directory?(@base_dir)
      Logger.info "Database '#{options[:name]}' not found!"
      self.class.create(options)
    end
  end

  def enchant(klass, manager)    
    super 

    klass.const_set 'OGNAME', klass.to_s.gsub(/::/, "/").downcase
    klass.property :oid, Fixnum
 
    FileUtils.mkdir_p(path(klass))
    File.open(spath(klass), 'w') { |f| f << '1' }
  rescue => ex
    Logger.error "Cannot create directory to store '#{klass}' classes!"                      
  end

  # :section: Lifecycle methods.

  def load(oid, klass)
    obj = nil
    File.open(path(klass, oid), 'r') { |f| obj = YAML::load(f.read) }
    return obj            
  rescue
    return nil
  end

  def reload(obj)
  end

  def save(obj)
    seq = nil
    File.open(spath(obj.class), 'r') { |f| seq = f.read.to_i }
    obj.oid = seq
    File.open(path(obj.class, obj.oid), 'w') { |f| f << obj.to_yaml }
    seq += 1
    File.open(spath(obj.class), 'w') { |f| f << seq }                        
  end

  def delete(obj_or_pk, klass = nil, cascade = true)
    pk = obj_or_pk.is_a?(Fixnum) ? obj_or_pk : obj_or_pk.oid
    klass ||= obj_or_pk.class
    FileUtils.rm(path(klass, pk))
  end

  def find
  end

  def count
  end

private

  # Path helper.

  def path(klass, pk = nil)
    class_dir = File.join(@base_dir, klass::OGNAME)
    pk ? File.join(class_dir, "#{pk}.yml") : class_dir
  end

  # Path to sequence helper.
  
  def spath(klass)
    File.join(path(klass), 'seq')
  end

end

end