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


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

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

  def makeEntry(fullyQualifiedFileName)
    title="", date=nil, text=""

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

    category = File.dirname(fullyQualifiedFileName).gsub(Config::ROOT_DATA_DIR, "")
    category.gsub!("/+", "/")
    category.gsub!("/+$", "")
    id = File.basename(fullyQualifiedFileName).split(".")[0]
    EntryData.new(id, title, text, date, category, Config::SITE_BASE_URL) 
  end

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


  public  #----------------------------------


# ----- TODO refactor following methods ------
# Rather than go directly to the Find command, I'm thinking that these 
# methods should delegate to a "query engine" that returns collections 
# of light file descriptors (perhaps just File.stat objects) that are 
# pre-filtered and ordered.  That would avoid the current inefficient 
# approach of # building up ALL entries # and sorting them, only to 
# ignore all but maxEntries of them.  Having a query engine also would 
# allow for transparent support of more sophisticated queries, rather 
# than the one type of query implemented here. This would be useful, 
# for example, in supporing single-article  views, date queries, etc. 

  def getLogEntries(path, maxEntries)
    logEntries = Array.new
    Find.find(path) {|file|  # recursively get all files
       logEntries << makeEntry(file) if /\.txt$/ =~ file
    }
    # ----- TODO this is going to get very inefficient!
    logEntries.sort.reverse[0...maxEntries]
  end

  def getLogEntriesCurrentDir(path)
    logEntries = Array.new
    entries    = Dir.entries(path)
    entries.grep(/\.txt/) { |fileName|
      logEntries << makeEntry(path + fileName)
    }
    logEntries.sort.reverse
  end

  def getAllSidebarEntries(path)
    sbEntries = Array.new
    entries    = Dir.entries(path)
    entries.grep(/\.box/) { |fileName|
      sbEntries << makeEntry(path + fileName)
    }
    sbEntries.sort.reverse
  end

  def getAllCategories(path)
    logCategories = Array.new

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


  # Consider caching below
  def getEntryTemplate
    makeTemplate(Config::TEMPLATE_DIR + "/" + Config::ENTRY_TEMPLATE)
  end

  def getSideboxTemplate
    makeTemplate(Config::TEMPLATE_DIR + "/" + Config::BOX_TEMPLATE)
  end

  def getBodyTemplate
    makeTemplate(Config::TEMPLATE_DIR + "/" + Config::BODY_TEMPLATE)
  end
end

