class Samovar::Options

Options provide a DSL for defining multiple option flags in a single block.
Represents a collection of command-line options.

def self.parse(*arguments, **options, &block)

@returns [Options] The frozen options collection.
@yields {|...| ...} A block that defines options using {#option}.
@parameter options [Hash] Additional options.
@parameter arguments [Array] The arguments for the options collection.

Parse and create an options collection from a block.
def self.parse(*arguments, **options, &block)
	options = self.new(*arguments, **options)
	
	options.instance_eval(&block) if block_given?
	
	return options.freeze
end

def << option

@parameter option [Option] The option to add.

Add an option to this collection.
def << option
	@ordered << option
	option.flags.each do |flag|
		@keyed[flag.prefix] = option
		
		flag.alternatives.each do |alternative|
			@keyed[alternative] = option
		end
	end
	
	if default = option.default
		@defaults[option.key] = option.default
	end
end

def each(&block)

@yields {|option| ...} Each option in the collection.

Iterate over each option.
def each(&block)
	@ordered.each(&block)
end

def empty?

@returns [Boolean] True if there are no options.

Check if this options collection is empty.
def empty?
	@ordered.empty?
end

def freeze

@returns [Options] The frozen options collection.

Freeze this options collection.
def freeze
	return self if frozen?
	
	@ordered.freeze
	@keyed.freeze
	@defaults.freeze
	
	@ordered.each(&:freeze)
	
	super
end

def initialize(title = "Options", key: :options)

@parameter key [Symbol] The key to use for storing parsed options.
@parameter title [String] The title for this options group in usage output.

Initialize a new options collection.
def initialize(title = "Options", key: :options)
	@title = title
	@ordered = []
	
	# We use this flag to option cache to improve parsing performance:
	@keyed = {}
	
	@key = key
	
	@defaults = {}
end

def initialize_dup(source)

@parameter source [Options] The source options to duplicate.

Initialize a duplicate of this options collection.
def initialize_dup(source)
	super
	
	@ordered = @ordered.dup
	@keyed = @keyed.dup
	@defaults = @defaults.dup
end

def merge!(options)

@parameter options [Options] The options to merge.

Merge another options collection into this one.
def merge!(options)
	options.each do |option|
		self << option
	end
end

def option(*arguments, **options, &block)

@yields {|value| ...} An optional block to transform the parsed value.
@parameter options [Hash] Additional options.
@parameter arguments [Array] The arguments for the option.

Define a new option in this collection.
def option(*arguments, **options, &block)
	self << Option.new(*arguments, **options, &block)
end

def parse(input, parent = nil, default = nil)

@returns [Hash] The parsed option values.
@parameter default [Hash | Nil] Default values to use.
@parameter parent [Command | Nil] The parent command.
@parameter input [Array(String)] The command-line arguments.

Parse options from the input.
def parse(input, parent = nil, default = nil)
	values = (default || @defaults).dup
	
	while option = @keyed[input.first]
		# prefix = input.first
		result = option.parse(input)
		if result != nil
			values[option.key] = result
		end
	end
	
	# Validate required options
	@ordered.each do |option|
		if option.required && !values.key?(option.key)
			raise MissingValueError.new(parent, option.key)
		end
	end
	
	return values
end		# Generate a string representation for usage output.

def to_s

@returns [String] The usage string.

Generate a string representation for usage output.
def to_s
	@ordered.collect(&:to_s).join(" ")
end

def usage(rows)

@parameter rows [Output::Rows] The rows to append usage information to.

Generate usage information for this options collection.
def usage(rows)
	@ordered.each do |option|
		rows << option
	end
end