#!/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
  attr_accessor :inspectorOverride
  
  def initialize(name, opts)
    @name = name
    @type = opts["type"] || "bool"
    @initial = opts["initial"]
    @conditional = opts["conditional"]
    @onChange = opts["onChange"]
    @getter = opts["getter"]
    @inspectorOverride = opts["inspectorOverride"]
  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 hasComplexGetter?
    hasInspectorOverride?
  end

  def setterFunctionName
    if @name.start_with?("css", "xss", "ftp", "dom", "dns", "ice")
      "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

  def hasInspectorOverride?
    @inspectorOverride == true
  end
end

class Conditional
  attr_accessor :condition
  attr_accessor :settings
  attr_accessor :boolSettings
  attr_accessor :nonBoolSettings
  attr_accessor :settingsWithComplexGetters
  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" }
    @settingsWithComplexGetters = @settings.select { |setting| setting.hasComplexGetter? }
    @settingsWithComplexSetters = @settings.select { |setting| setting.hasComplexSetter? }
  end
end

class Settings
  attr_accessor :settings
  attr_accessor :unconditionalSetting
  attr_accessor :unconditionalBoolSetting
  attr_accessor :unconditionalNonBoolSetting
  attr_accessor :unconditionalSettingWithComplexGetters
  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" }
    @unconditionalSettingWithComplexGetters = @unconditionalSetting.select { |setting| setting.hasComplexGetter? }
    @unconditionalSettingWithComplexSetters = @unconditionalSetting.select { |setting| setting.hasComplexSetter? }
    @inspectorOverrideSettings = @settings.select { |setting| setting.hasInspectorOverride? }

    @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"))
