#!/usr/bin/ruby
#================================================
# Classes for a file-based model
#================================================
require "config.rb"
require "store.rb"
require "model.rb"
require "find.rb"
require "date.rb"


#--------------------------------------------------------
# FileSystemQuery
# A query that takes a criteria and returns entry objects
# derived from the filesystem.
#--------------------------------------------------------
class FileSystemQuery
  def make_entry(fully_qualified_file_name)
    title="", date=nil, text=""

    File.open(fully_qualified_file_name) { |file|
      title = file.gets.chomp!  #first line is title
      text = ""
      file.each_line { |line|
        text << line 
      }
      date = File.stat(fully_qualified_file_name).mtime
    }

    category = File.dirname(fully_qualified_file_name).gsub(Config::ROOT_DATA_DIR, "")
    category.gsub!("/+", "/")
    category.gsub!("/+$", "")
    id = File.basename(fully_qualified_file_name, ".txt") + ".html"
    LogEntryData.new(id, title, text, date, category, Config::SITE_BASE_URL)
  end

  def make_404_entry
    LogEntryData.new("error.html",
                     "404 - Article Not Found", "I looked really hard, but couldn't find the specified article.  Bummer.",
                     DateTime.now, "",
                     Config::ROOT_DATA_DIR)  
  end

  def criteria_to_file_path(criteria)
    (Config::ROOT_DATA_DIR + criteria).sub(/\.html$/, ".txt")
  end
end

#--------------------------------------------------------
# LogEntryQuery
# A query that takes a criteria and returns LogEntry objects
# derived from the filesystem.
#--------------------------------------------------------
class LogEntryQuery < FileSystemQuery

  def execute(criteria, max_entries)
    entries = Array.new
    file_path = criteria_to_file_path(criteria.expression)

    begin
      Find.find(file_path) {|file|  # recursively get all files
        if !File.directory?(file) and file =~ /\.txt$/
          entries << make_entry(file)
        end
      }
      
      rescue Exception => e
        entries << make_404_entry
    end
    entries
  end
end

#--------------------------------------------------------
# SidebarEntryQuery
# A query that takes a criteria and returns SidebarEntryQuery
# objects derived from the filesystem.
#--------------------------------------------------------
class SidebarEntryQuery < FileSystemQuery
  def execute(criteria)
    entries = Array.new
    file_path = criteria_to_file_path(criteria.expression)
    file_path = File.dirname(file_path) if !File.directory?(file_path)
    
    begin
      # Get just local dir .box files (not recursive)
      dir_listing = Dir.entries(file_path)
      rescue
        file_path = Config::ROOT_DATA_DIR
        dir_listing = Dir.entries(file_path)
      ensure
        dir_listing.grep(/\.box/) { |file_name|
          entries << make_entry(file_path + "/" + file_name)
        }
      end
    entries
  end
end


#------------------------------------------------
# FileStore - represents where we get our stuff 
#------------------------------------------------
class FileStore < Store

  protected #----------------------------------

  def make_template(fully_qualified_file_name)
    text = ""
    File.open(fully_qualified_file_name) { |file|
      text = file.gets(nil)
    }
    Template.new(text)
  end

  
  public  #----------------------------------
  
  def get_all_log_entries(criteria, max_entries)
    entries = LogEntryQuery.new.execute(criteria, max_entries)
    entries.sort.reverse[0...max_entries]
  end

  def get_all_sidebar_entries(criteria)
    entries = SidebarEntryQuery.new.execute(criteria)
    entries.sort.reverse
  end

  def get_all_categories()
    logCategories = Array.new

    Find.find(Config::ROOT_DATA_DIR) { |f| 
      if f != Config::ROOT_DATA_DIR
        if File.directory? f
          file_name = f.gsub(Config::ROOT_DATA_DIR + "/", "")
          num_entries = Dir.entries(f).grep(/\.txt$/).size
          logCategories << CategoryData.new("/" + file_name, num_entries)
        end
      end
    }
    logCategories.sort
  end

  # Consider caching below
  def get_entry_template
    make_template(Config::TEMPLATE_DIR + "/" + Config::ENTRY_TEMPLATE)
  end

  def get_sidebox_template
    make_template(Config::TEMPLATE_DIR + "/" + Config::BOX_TEMPLATE)
  end

  def get_body_template
    make_template(Config::TEMPLATE_DIR + "/" + Config::BODY_TEMPLATE)
  end
end

