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

require "optparse"
$LOAD_PATH << "../../lib" unless $LOAD_PATH.include?("../../lib")
require "qwik/version"

module Qwik
  class Config
    def initialize(debug=false, test=false)
      @debug = debug
      @test  = test

      File.umask(0)

      # Setting for directories.
      base_dir = File.expand_path(File.dirname(__FILE__)+"/../../")
      @bin_dir		= base_dir+"/bin"
      @lib_dir		= base_dir+"/lib"
      @log_dir		= base_dir+"/log"
      @etc_dir		= base_dir+"/etc"
      @data_dir		= base_dir+"/data"
      @grave_dir	= base_dir+"/grave"
      @cache_dir	= base_dir+"/cache"

      @qwiklib_dir	= @lib_dir+"/qwik"
      @super_dir	= @lib_dir+"/super"
      @theme_dir	= @lib_dir+"/theme"
      @template_dir	= @lib_dir+"/template"
      @catalog_dir	= @lib_dir+"/catalog"
      @qrcode_dir	= @lib_dir+"/qrcode"

      default_config_file	= @etc_dir+"/config-default.txt"
      config_file	= @etc_dir+"/config.txt"
      @pass_file	= @etc_dir+"/password.txt"
      @generation_file	= @etc_dir+"/generation.txt"

      @pid_file		= @log_dir+"/qwikweb.pid"
      @log_file		= @log_dir+"/qwikweb.log"
      @accesslog_file	= @log_dir+"/access.log"
      @qlog_file	= @log_dir+"/qwik-access.log"

      # Setting.
      @ssl		= false

      # Read default config file.
      read_config(default_config_file)

      # Read config file.
      read_config(config_file)

      # Make instance variables readable.
      make_instance_variables_readable
    end

    def read_config(file)
      raise "can not open "+file if ! FileTest.exist?(file)
      str = open(file) {|f| f.read }
      h = parse_config(str)
      set_config(h)
    end

    def parse_config(str)
      h = {}
      str.each_line {|line|
	line.chomp!
	next unless line[0] == ?:
	ar = line.chomp.split(":", 3)
	h[ar[1]] = ar[2]
      }
      h
    end

    def set_config(h)
      h.each {|k, v|
	self.instance_variable_set("@"+k, v)
      }
    end

    def make_instance_variables_readable
      instance_variables.each {|name|
	self.class.class_eval {
	  attr_reader(name.delete("@"))
	}
      }

      if @debug # for test
	instance_variables.each {|name|
	  self.class.class_eval {
	    attr_writer(name.delete("@"))
	  }
	}
      end
    end

    # called from server.rb
    def parse_args(args)
      optionparser = OptionParser.new {|opts|
	opts.banner = "Usage: qwikweb.rb [options]"

	opts.separator ""
	opts.separator "Specific options:"

	opts.on("-d", "--[no-]debug", "Run in debug mode") {|a|
	  @debug = a
	}

	opts.on("-p", "--port n", OptionParser::DecimalInteger,
		"Port to open.") {|a|
	  @port = a
	}

	opts.on("-h", "--host expample.com", "Default hostname.") {|a|
	  @default_hostname = a
	}

	opts.on("-s", "--[no-]ssl", "Run in SSL mode") {|a|
	  @ssl = a
	}

	opts.separator ""
	opts.separator "Common options:"

	# "-h" is used in --host
	opts.on_tail("--help", "Show this message") {
	  puts opts
	  exit
	}

	opts.on_tail("--version", "Show version") {
	  puts Config::VERSION
	  exit
	}
      }
      
      optionparser.parse!(args)
    end

  end
end

if $0 == __FILE__
  $debug = true
end

if $debug
  require "test/unit"

  class TC_Config < Test::Unit::TestCase
    def test_all
      # test_config
      @config = Qwik::Config.new

      # do not test it.
      #base_dir = File.expand_path(File.dirname(__FILE__)+"/../../")
      #assert_equal(base_dir+"/bin", @config.bin_dir)

      # test debug mode
      assert_equal(false, @config.debug)
      @config = Qwik::Config.new(true)
      assert_equal(true, @config.debug)

      # test parse_config
      h = @config.parse_config(":testparam:This is a test.")
      assert_equal({"testparam"=>"This is a test."}, h)
      # test set_config
      @config.set_config(h)
      # test make_instance_variables_readable
      @config.make_instance_variables_readable
      assert_equal("This is a test.", @config.testparam)

      # test read_config
      # @config.read_config(@config.etc_dir+"/config.txt")
      #assert_equal("127.0.0.1", @config.default_hostname)
      #assert_equal("c:/usr/RealProducer/producer.exe", @config.real_producer)
      #assert_equal("c:/usr/HelixServer/Content", @config.real_server_content)
    end

    def test_args
      @config = Qwik::Config.new

      assert_equal(false, @config.debug)
      @config.parse_args(["-d"])
      assert_equal(true, @config.debug)

      assert_equal("9190", @config.port)
      @config.parse_args(["-p", "80"])
      assert_equal(80, @config.port)
      
      assert_equal("example.com", @config.default_hostname)
      @config.parse_args(["-h", "e.com"])
      assert_equal("e.com", @config.default_hostname)
    end
  end
end
