module Fewer
  class App
    class << self
      def [](name)
        apps[name]
      end

      def apps
        @apps ||= {}
      end
    end

    attr_reader :name, :engine_klass, :cache, :root

    def initialize(name, options = {})
      @engine_klass = options[:engine]
      @mount = options[:mount]
      @root = options[:root]
      @cache = options[:cache] || 3600 * 24 * 365
      raise 'You need to define an :engine class' unless @engine_klass
      raise 'You need to define a :root path' unless @root
      self.class.apps[name] = self
    end

    def call(env)
      names = names_from_path(env['PATH_INFO'])
      engine = engine_klass.new(root, names)
      headers = {
        'Content-Type' => engine.content_type,
        'Cache-Control' => "public, max-age=#{cache}"
      }

      [200, headers, [engine.read]]
    rescue Fewer::MissingSourceFileError => e
      [404, { 'Content-Type' => 'text/plain' }, [e.message]]
    rescue => e
      [500, { 'Content-Type' => 'text/plain' }, ["#{e.class}: #{e.message}"]]
    end

    private
      def names_from_path(path)
        encoded = File.basename(path, '.*')
        Serializer.decode(encoded)
      end
  end
end

module Fewer
  class App
    class << self
      def [](name)
        apps[name]
      end

      def apps
        @apps ||= {}
      end
    end

    attr_reader :name, :engine_klass, :cache, :root

    def initialize(name, options = {})
      @engine_klass = options[:engine]
      @mount = options[:mount]
      @root = options[:root]
      @cache = options[:cache] || 3600 * 24 * 365
      raise 'You need to define an :engine class' unless @engine_klass
      raise 'You need to define a :root path' unless @root
      self.class.apps[name] = self
    end

    def call(env)
      eng = engine(names_from_path(env['PATH_INFO']))
      headers = {
        'Content-Type' => eng.content_type,
        'Cache-Control' => "public, max-age=#{cache}"
      }

      [200, headers, [eng.read]]
    rescue Fewer::MissingSourceFileError => e
      [404, { 'Content-Type' => 'text/plain' }, [e.message]]
    rescue => e
      [500, { 'Content-Type' => 'text/plain' }, ["#{e.class}: #{e.message}"]]
    end

    def engine(names)
      engine_klass.new(root, names)
    end

    private
      def names_from_path(path)
        encoded = File.basename(path, '.*')
        Serializer.decode(encoded)
      end
  end
end

Add method to fetch instantiated engine directly from App.
Add method to fetch instantiated engine directly from App.
