#!/usr/bin/env ruby
#
# Copyright (c) 2017 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.

require "fileutils"
require 'erb'
require 'optparse'
require 'yaml'

options = { 
  :input => nil,
  :outputDirectory => nil
}
optparse = OptionParser.new do |opts|
    opts.banner = "Usage: #{File.basename($0)} --input file"

    opts.separator ""

    opts.on("--input input", "file to generate settings from") { |input| options[:input] = input }
    opts.on("--outputDir output", "directory to generate file in") { |output| options[:outputDirectory] = output }
end

optparse.parse!

if !options[:input]
  puts optparse
  exit -1
end

if !options[:outputDirectory]
  options[:outputDirectory] = Dir.getwd
end

FileUtils.mkdir_p(options[:outputDirectory])

parsedSettings = begin
  YAML.load_file(options[:input])
rescue ArgumentError => e
  puts "Could not parse input file: #{e.message}"
  exit(-1)
end

class Setting
  attr_accessor :name
  attr_accessor :type
  attr_accessor :initial
  attr_accessor :conditional
  attr_accessor :onChange
  attr_accessor :getter
  
  def initialize(name, opts)
    @name = name
    @type = opts["type"] || "bool"
    @initial = opts["initial"]
    @conditional = opts["conditional"]
    @onChange = opts["onChange"]
    @getter = opts["getter"]
  end

  def valueType?
    @type != "String" && @type != "URL"
  end

  def idlType
    # FIXME: Add support for more types including enumerate types.
    if @type == "int"
      "long"
    elsif @type == "unsigned"
      "unsigned long"
    elsif @type == "double"
      "double"
    elsif @type == "float"
      "float"
    elsif @type == "String"
      "DOMString"
    elsif @type == "bool"
      "boolean"
    else
      nil
    end
  end

  def parameterType
    if valueType?
      @type
    else
      "const #{@type}&"
    end
  end

  def hasComplexSetter?
    @onChange != nil
  end

  def setterFunctionName
    if @name.start_with?("css", "xss", "ftp", "dom", "dns")
      "set" + @name[0..2].upcase + @name[3..@name.length]
    else
      "set" + @name[0].upcase + @name[1..@name.length]
    end
  end

  def getterFunctionName
    @getter || @name
  end
end

class Conditional
  attr_accessor :condition
  attr_accessor :settings
  attr_accessor :boolSettings
  attr_accessor :nonBoolSettings
  attr_accessor :settingsWithComplexSetters

  def initialize(condition, settings)
    @condition = condition
    @settings = settings
    
    @boolSettings = @settings.select { |setting| setting.type == "bool" }
    @nonBoolSettings = @settings.reject { |setting| setting.type == "bool" }
    @settingsWithComplexSetters = @settings.select { |setting| setting.hasComplexSetter? }
  end
end

class Settings
  attr_accessor :settings
  attr_accessor :unconditionalSetting
  attr_accessor :unconditionalBoolSetting
  attr_accessor :unconditionalNonBoolSetting
  attr_accessor :unconditionalSettingWithComplexSetters
  attr_accessor :conditionals
  
  def initialize(hash)
    @settings = []
    hash.each do |name, options|
      @settings << Setting.new(name, options)
    end
    @settings.sort! { |x, y| x.name <=> y.name }
    
    @unconditionalSetting = @settings.reject { |setting| setting.conditional }
    @unconditionalBoolSetting = @unconditionalSetting.select { |setting| setting.type == "bool" }
    @unconditionalNonBoolSetting = @unconditionalSetting.reject { |setting| setting.type == "bool" }
    @unconditionalSettingWithComplexSetters = @unconditionalSetting.select { |setting| setting.hasComplexSetter? }

    @conditionals = []
    conditionalsMap = {}
    @settings.select { |setting| setting.conditional }.each do |setting|
      if !conditionalsMap[setting.conditional]
        conditionalsMap[setting.conditional] = []
      end

      conditionalsMap[setting.conditional] << setting
    end
    conditionalsMap.each do |key, value|
      @conditionals << Conditional.new(key, value)
    end
    @conditionals.sort! { |x, y| x.condition <=> y.condition }
  end

  def renderToFile(template, file)
    template = File.join(File.dirname(__FILE__), template)

    output = ERB.new(File.read(template), 0, "-").result(binding)
    File.open(file, "w+") do |f|
      f.write(output)
    end
  end
end

settings = Settings.new(parsedSettings)
settings.renderToFile("SettingsTemplates/Settings.h.erb", File.join(options[:outputDirectory], "Settings.h"))
settings.renderToFile("SettingsTemplates/Settings.cpp.erb", File.join(options[:outputDirectory], "Settings.cpp"))
settings.renderToFile("SettingsTemplates/InternalSettingsGenerated.idl.erb", File.join(options[:outputDirectory], "InternalSettingsGenerated.idl"))
settings.renderToFile("SettingsTemplates/InternalSettingsGenerated.h.erb", File.join(options[:outputDirectory], "InternalSettingsGenerated.h"))
settings.renderToFile("SettingsTemplates/InternalSettingsGenerated.cpp.erb", File.join(options[:outputDirectory], "InternalSettingsGenerated.cpp"))
