#---
# Author::  Ian Yang
# Created:: <2010-06-10 21:32:29>
#+++
#
# Generate RouterInitializer.cpp
require 'rubygems'
require 'yaml'

source = File.dirname(File.dirname(File.expand_path(__FILE__)))

config_file = File.join(File.dirname(__FILE__), "router_initializer.yml")
cpp_file = File.join(source, "process", "common", "RouterInitializer.cpp")

if File.exist?(cpp_file) && File.mtime(cpp_file) > File.mtime(config_file)
  puts "RouterInitializer.cpp is newer than config file. Quit."
end

config = YAML.load_file(config_file)

cpp = ""

cpp += <<HEADER
/**
 * @file process/RouterInitializer.cpp
 * @date Created <#{DateTime.now.strftime "%Y-%m-%d %H:%M:%S"}>
 *
 * This file is generated by generators/router_initializer.rb from config file
 * generators/router_initializer.yml. Do not edit this file directly. Please read
 * the config file, update options there and re-run the ruby script to
 * update this file.
 */

#include "RouterInitializer.h"
#include <util/driver/ActionHandler.h>

#include <memory> // for std::auto_ptr

HEADER

config["headers"].each do |h|
  cpp += "#include \"#{h}\"\n"
end

cpp += <<FUNCSTART

namespace sf1r
{

void initializeDriverRouter(::izenelib::driver::Router& router, IService* service, bool enableTest)
{
FUNCSTART
  
config["controllers"].each do |type, spec|
  spec ||= {}
  name = spec["name"]
  if name.nil?
    name = type.sub(/Controller$/, "").gsub(/([a-z])([A-Z])/, '\1_\2').downcase
  end
  global = spec["global"] ? "true" : "false";
  initializer = spec["initializer"] || "#{type} #{name};"

  actions = ["index"]
  if spec["actions"]
    actions = spec["actions"].sort.uniq
  end

  unless actions.empty?
    if spec["test"]
      cpp += "    if (enableTest)\n"
    end
    cpp += <<CONTROLLERSTART
    {
        #{initializer}
        const std::string controllerName(#{name.inspect});
        typedef ::izenelib::driver::ActionHandler<#{type}> handler_type;
        typedef std::auto_ptr<handler_type> handler_ptr;
CONTROLLERSTART

    actions.each do |action|
      cpp += <<ACTION

        handler_ptr #{action}Handler(
            new handler_type(
                #{name},
                &#{type}::#{action}
            )
        );

        router.map(
            controllerName,
            #{action.inspect},
            #{action}Handler.get()
        );
        #{action}Handler.release();
ACTION
    end

    cpp += <<CONTROLLEREND
    }

CONTROLLEREND
  end
end

cpp += <<FUNCEND
}

} // namespace sf1r

FUNCEND

File.open(cpp_file, "w") do |f|
  f.write(cpp)
end

