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

$LOAD_PATH << "../../lib" unless $LOAD_PATH.include?("../../lib")
require "qwik/webrick"
require "qwik/config"
require "qwik/memory"
#require "qwik/catalog"
require "qwik/logger"
require "qwik/action"
require "qwik/periodic"
require "qwik/request"
require "qwik/response"
require "qwik/loadlib"

require "qwik/servlet"

module Qwik
  class QwikWebServer
    def self.main(argv)
      config = Config.new
      config.parse_args(argv)
      memory = ServerMemory.new(config)
      server = Server.new(config, memory)
      server.start
    end
  end

  class Server < WEBrick::HTTPServer
    def initialize(qconfig, memory)
      @qconfig = qconfig
      @memory  = memory

      init_trap

      init_directory(@qconfig)

      webrick_conf = init_webrick_conf(@qconfig, @memory)
      super(webrick_conf)

      loadlib = LoadLibrary.new
      loadlib.glob(@qconfig.lib_dir, "qwik/act-*.rb")

      mount("/", Servlet) # Delegate all access.
    end

    def init_trap
      trap(:TERM) { shutdown; }
      trap(:INT)  { shutdown; }
    end

    def init_directory(config)
      config.log_dir.path.check_directory
      config.etc_dir.path.check_directory
      config.data_dir.path.check_directory
      (config.data_dir.path+config.default_sitename).check_directory
      config.cache_dir.path.check_directory
      config.grave_dir.path.check_directory
    end

    def init_webrick_conf(config, memory)
      logfile  = config.log_file		# qwikweb.log
      @pidfile  = config.pid_file
      servertype = WEBrick::Daemon
      if config.debug
	@pidfile += "-d"
	servertype = WEBrick::SimpleServer
	logfile = $stdout
	logfile = "testlog.txt" if config.test
      end

      # qwik-access.log
      @memory[:accesslog] = Qwik::AccessLog.new(config, config.qlog_file)

      logger = WEBrick::Log.new(logfile, WEBrick::Log::INFO)
      memory[:logger] = logger

      webrick_config = {
	:HostnameLookups => false,
	:BindAddress	=> config.bind_address,
	:Port		=> config.port.to_i,
	:Logger		=> logger,
	:ServerType	=> servertype,
	:StartCallback	=> Proc.new { start_server },
	:AccessLog	=>
	[[ WEBrick::BasicLog.new(config.accesslog_file, WEBrick::Log::INFO),
	    WEBrick::AccessLog::COMBINED_LOG_FORMAT ]],
	:ServerSoftware	=> "qwikWeb/"+Config::VERSION+"+"+Config::RELEASE_DATE,
	:QwikConfig	=> config,
	:QwikMemory	=> memory,
	:StopCallback	=> Proc.new { p "stop"; }, # for test
       #:WEBrickThread  => false, # test
      }

      return webrick_config
    end

    # callback from StartCallback
    def start_server
      write_pid_file

      threads = []
      threads <<            SweepThread.new(@qconfig, @memory)
      threads << WeeklySendReportThread.new(@qconfig, @memory)
      threads <<  DailySendReportThread.new(@qconfig, @memory)
      threads << HourlySendReportThread.new(@qconfig, @memory)
      @memory[:threads] = threads
      threads.each {|th|
	t = Thread.new { th.start }
	t.abort_on_exception = true
      }

      if @qconfig.debug
	require "qwik/autoreload"
	autoreload(1, true) # auto reload
      end
    end

    def write_pid_file
      File.open(@pidfile, "wb") {|f| f.puts Process.pid }
    end

    def read_pid_file
      open(@pidfile, "rb"){|f| f.read}.chomp.to_i
    end

    def remove_pid_file
      File.unlink(@pidfile) if Process.pid == read_pid_file
    end
  end
end
