module Rad
  class Config < SafeHash
    inherit ::OpenConstructor
    
    DEFAULTS = {}
    RUNTIME = {}

    def initialize
      super

      DEFAULTS.each{|k, v| self[k] = v}
      RUNTIME.each{|k, v| self[k] = v}
    end    
    
    # trying to load both file_path and file_path.environment files if they are exists
    def merge_config! file_path      
      # unless ::Micon.include? :config
      #   raise("this method should be called only after config already initialized (use app.after :config do ... end)!")
      # end
      raise("config file must have .yml extension (#{file_path})!") unless file_path.end_with? '.yml'
      default_file_path = file_path.sub(/yml$/, "default.yml")
      file_path_for_current_environment = file_path.sub(/yml$/, "#{environment!}.yml")
      [
        default_file_path,
        file_path,
        file_path_for_current_environment
      ].each do |cfile|
        if ::File.exist? cfile 
          data = ::YAML.load_file cfile
          if data
            data.must_be.a ::Hash
            self.deep_merge! data            
          end
        end
      end
    end
    
    # 
    # runtime_dir
    # 
    def runtime_dir= runtime_dir
      if runtime_dir
        self[:runtime_dir] = ::File.expand_path(runtime_dir)
      else
        self.delete 'runtime_dir'
      end
    end
    
    
    #
    # public_dir
    #
    def public_dir 
      runtime_dir? ? "#{runtime_dir}/public" : self[:public_dir] 
    end
    def public_dir?; runtime_dir? end
    def public_dir!
      "#{runtime_dir!}/public"
    end
    
    
    # 
    # environment
    # 
    def environment= env
      env = env.to_s
      env.must_be.in %w{production development test}
      self['environment'] = env
    end
  
    def development?; environment == 'development' end
    def production?; environment == 'production' end
    def test?; environment == 'test' end    
    
    def development &block; block.call if development? end
    def production &block; block.call if production? end
    def test &block; block.call if test? end
    
    # 
    # log_path
    # 
    attr_writer :log_path
    def log_path
      @log_path ||= runtime_dir? ? "#{runtime_dir}/log/#{environment}.log" : ""
    end
    
    
    # 
    # log_level
    # 
    attr_writer :log_level
    def log_level
      @log_level ||= production? ? :info : :debug
    end
    
    
    # 
    # session
    # 
    # key: 'rack.session', domain: 'foo.com', path: '/', expire_after: 2592000, secret: 'change_me'
    # attr_accessor :session
    # def session?; !!session end
      
      
    # class << self
    #   attr_accessor :command_line_config
    #   
    #   def defered_configs; @defered_configs ||= [] end
    # end
  end
end