# Copyright 2011 Rapleaf
# 
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# 
#    http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

class TemplateProcessor
  def self.autogenerated
<<EOF
/**
 * Autogenerated by Jack
 *
 * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
 */
EOF
  end
  
  
  private


  JACK_NAMESPACE = "com.rapleaf.jack"

  def self.adjust(s) 
    s.gsub(/^\s+<%(.*).%>$/, "<%\\1%>")
  end

  def self.load_template(file_name)
    ERB.new(adjust(File.read(File.dirname(__FILE__) + "/" + file_name)), nil, "<>")
  end

  DB_INTERFACE_TEMPLATE = load_template("templates/db_interface.erb")
  DB_IMPL_TEMPLATE = load_template("templates/db_impl.erb")
  DB_FIXTURES_TEMPLATE = load_template("templates/db_fixtures.erb")
  PERSISTENCE_INTERFACE_TEMPLATE = load_template("templates/persistence_interface.erb")
  MODEL_TEMPLATE = load_template("templates/model.erb")
  PERSISTENCE_IMPL_TEMPLATE = load_template("templates/persistence_impl.erb")

  DATABASES_IFACE_TEMPLATE = load_template("templates/databases_iface.erb")
  DATABASES_IMPL_TEMPLATE = load_template("templates/databases_impl.erb")

  QUERY_BUILDER_TEMPLATE = load_template("templates/query_builder_impl.erb")

  DELETE_BUILDER_TEMPLATE = load_template("templates/delete_builder_impl.erb")

  CREATE_METHOD_TEMPLATE = load_template("templates/create_method.erb")

  MIGRATION_TXT_TEMPLATE = load_template("templates/migration.erb");

  public

  def self.process(project_defn, output_dir, model_defns_by_namespace_table_names, migration_number)
    project_defn.databases.each do |database_defn|
      by_table_name = model_defns_by_namespace_table_names[database_defn.namespace]

      process_database_defn(project_defn, database_defn, output_dir, by_table_name.values.sort_by{|x| x.table_name}, by_table_name)
    end

    output_dir = output_dir + "/" + project_defn.databases_namespace.gsub(".", "/")
    file = File.new("#{output_dir}/IDatabases.java", "w")
    file.puts(DATABASES_IFACE_TEMPLATE.result(binding))
    file.close

    file = File.new("#{output_dir}/DatabasesImpl.java", "w")
    file.puts(DATABASES_IMPL_TEMPLATE.result(binding))
    file.close
    
    file = File.new("#{output_dir}/migration-version.txt", "w")
    file.puts(MIGRATION_TXT_TEMPLATE.result(binding))
    file.close
  end
  
  def self.process_database_defn(project_defn, database_defn, output_dir, model_defns, by_table_name)
    output_dir = output_dir.dup + "/" + database_defn.namespace.gsub(".", "/")

    FileUtils.mkdir_p("#{output_dir}")
    FileUtils.mkdir_p("#{output_dir}/models/")
    FileUtils.mkdir_p("#{output_dir}/iface/")
    FileUtils.mkdir_p("#{output_dir}/impl/")
    FileUtils.mkdir_p("#{output_dir}/query/")


    db_name = database_defn.name
    root_package = database_defn.namespace

    model_defns.each do |model_defn|
      create_signature_full = model_defn.create_signature_full
      create_signature_small = model_defn.create_signature_small
      create_argument_defaults = model_defn.create_argument_defaults

      file = File.new("#{output_dir}/models/#{model_defn.model_name}.java", "w")
      file.puts(MODEL_TEMPLATE.result(binding))
      file.close

      file = File.new("#{output_dir}/iface/#{model_defn.iface_name}.java", "w")
      file.puts(PERSISTENCE_INTERFACE_TEMPLATE.result(binding))
      file.close

      file = File.new("#{output_dir}/impl/#{model_defn.impl_name}.java", "w")
      file.puts(PERSISTENCE_IMPL_TEMPLATE.result(binding));
      file.close

      file = File.new("#{output_dir}/query/#{model_defn.query_builder_name}.java", "w")
      file.puts(QUERY_BUILDER_TEMPLATE.result(binding));
      file.close

      file = File.new("#{output_dir}/query/#{model_defn.delete_builder_name}.java", "w")
      file.puts(DELETE_BUILDER_TEMPLATE.result(binding));
      file.close


    end

    file = File.new("#{output_dir}/I#{db_name}.java", "w")
    file.puts(DB_INTERFACE_TEMPLATE.result(binding))
    file.close

    file = File.new("#{output_dir}/impl/#{db_name}Impl.java", "w")
    file.puts(DB_IMPL_TEMPLATE.result(binding))
    file.close

    file = File.new("#{output_dir}/Base#{db_name}Fixtures.java", "w")
    file.puts(DB_FIXTURES_TEMPLATE.result(binding))
    file.close
  end

  def self.render_create_method(model_defn, signature, only_not_null = false)
    CREATE_METHOD_TEMPLATE.result(binding)
  end

end
