# Copyright (C) 2003-2005 Kouichirou Eto, All rights reserved.

$LOAD_PATH << "../../lib" unless $LOAD_PATH.include?("../../lib")
require "qwik/config"
require "qwik/site"
require "qwik/util-path"

module Qwik
  # Bundle many sites to one object.
  class Farm
    def initialize(config, memory)
      @config = config
      @memory = memory
      @logger = @memory[:logger]
      @data_path = @config.data_dir.path
      @grave_path = @config.grave_dir.path
      @grave_path.check_directory
      @sites = {}
    end

    def get_default_site
      get_site(@config.default_sitename)
    end

    def exist?(s)
      get_site(s) != nil
    end

    def get_site(s)
      d = @data_path+s
      # FIXME: Should we check the directory everytime?
      unless d.directory? # check directory first
	@sites.delete(s) if @sites[s] # delete the site
	return nil # no such site
      end

      @sites[s] = Site.new(@config, @memory, s) if @sites[s].nil? # create
      @sites[s]
    end

    def make_site(s)
      d = @data_path+s
      raise "site already exist" if d.exist? # check the dir first
      d.mkdir
      nil
    end

    def close_all
      each {|s|
	site = get_site(s)
	site.close
      }
    end

    def each
      check_all_sites
      @sites.keys.sort.each {|s|
	yield(s)
      }
    end

    def sweep
      @logger.log(WEBrick::Log::INFO, "start sweep") unless $debug
      inactive_sites = check_inactive_sites
      buried = []
      inactive_sites.each {|s|
	@logger.log(WEBrick::Log::INFO, "sweep "+s) unless $debug
	g = bury(s)
	buried << g
      }
      buried
    end

    def check_inactive_sites
      inactive_sites = []
      self.each {|s|
	next if s == @config.default_sitename # do not bury default site
	site = get_site(s)
	next if site.nil?
	next if ! site.inactive?
	inactive_sites << s
      }
      inactive_sites
    end

    private

    def bury(s)
      site = get_site(s)
      sitepath = (site.dir).path
      dirtime = sitepath.mtime.to_i
      while true
	g = @grave_path+(dirtime.to_s+"_"+s.to_s)
	if !g.exist?
	  sitepath.rename(g)
	  break
	end
	dirtime += 1
      end
      g
    end

    def check_all_sites
      @sites.each {|s, site| # At the first, check obsolete sites.
	dummy = get_site(s)
      }

      @data_path.each_entry {|s| # Then, check the direcotry entries.
	next unless (@data_path+s).directory? # is not directory?
	ss = s.to_s
	next if ss[0] == ?. # begin with dot?
	next if ss == "CVS"
	dummy = get_site(ss)
      }
    end
  end
end

if $0 == __FILE__
  $LOAD_PATH << "../../lib" unless $LOAD_PATH.include?("../../lib")
  require "qwik/test-module-session"
  $debug = true
end

if $debug
  class TC_Farm < Test::Unit::TestCase
    include TestSession

    def test_make_site
      farm = @memory.farm
      farm.close_all
      @dir.teardown
      @dir.rmtree if @dir.directory?
      @dir.rmdir  if @dir.directory?

      # test_exist?
      assert_equal(false, farm.exist?("test"))
      assert_equal(nil, farm.get_site("test"))

      # test_make_site
      farm.make_site("test")
      assert_equal(true, farm.exist?("test"))
      assert_instance_of(Qwik::Site, farm.get_site("test"))
      # make again cause exception.
      assert_raise(RuntimeError){
	farm.make_site("test") # test raise
      }
    end

    def test_all
      farm = @memory.farm

      # test_default_site
      site = farm.get_default_site
      assert_instance_of(Qwik::Site, site)
      assert_equal(@config.default_sitename, site.sitename)
      assert_equal(true, farm.exist?("www"))
      assert_instance_of(Qwik::Site, farm.get_site("www"))

      # test_each
      farm.each {|s|
	assert_instance_of(String, s)
      }
    end

    def test_sweep
      farm = @memory.farm

      site = farm.get_site("test")
      page = site["_SiteConfig"]
      page.store(":ml_life_time:0") # die soon.

      # test_inactive?
      assert_equal(true, site.inactive?)

      # test_sweep
      buried = farm.sweep
      site = farm.get_site("test")
      assert_equal(nil, site)
      buried.each {|pa|
	pa.teardown
	pa.rmtree
      }
    end
  end
end
