# frozen_string_literal: true

require 'env_paths'
require 'optparse'

module StartupTime
  # StartupTime::Options - a struct-like interface to the app options set or
  # overridden on the command line
  class Options
    BUILD_DIR = EnvPaths.get('startup-time', suffix: false).cache
    ROUNDS = 10

    attr_reader :action, :build_dir, :format, :rounds, :verbosity

    include Services.mixin %i[registry]

    def initialize(args)
      @action = :benchmark
      @build_dir = BUILD_DIR
      @format = :default
      @parser = nil
      @rounds = ROUNDS
      @verbosity = :default

      parse! args
    end

    # the usage message (string) generated by the option parser for this tool
    def usage
      @parser.to_s
    end

    private

    # process the command-line options and assign values to the corresponding
    # instance variables
    def parse!(args)
      @parser = OptionParser.new do |opts|
        opts.on(
          '-c',
          '--count',
          '--rounds INTEGER',
          Integer,
          "The number of times to execute each test (default: #{ROUNDS})"
        ) do |value|
          @rounds = value
        end

        opts.on(
          '--clean',
          'Remove the build directory and exit (targets will be ',
          'recompiled on the next run)'
        ) do
          @action = :clean
        end

        opts.on(
          '-d',
          '--dir PATH',
          String,
          "Specify the build directory (default: #{BUILD_DIR})"
        ) do |value|
          @build_dir = value
        end

        opts.on(
          '-h',
          '--help',
          'Show this help message and exit'
        ) do
          @action = :help
        end

        opts.on(
          '-H',
          '--help-only',
          '--help-omit',
          'Show the IDs and groups that can be passed to --only and --omit'
        ) do
          @action = :show_ids
        end

        opts.on(
          '-j',
          '--json',
          'Output the results in JSON format (implies --quiet)'
        ) do
          @format = :json
          @verbosity = :quiet
        end

        opts.on(
          '-o',
          '--only LIST',
          Array, # comma-separated strings
          'Only execute the specified tests (comma-separated list of ',
          'IDs/groups)'
        ) do |values|
          values.each { |value| registry.only(value.strip) }
        end

        opts.on(
          '-O',
          '--omit LIST',
          Array, # comma-separated strings
          "Don't execute the specified tests (comma-separated list ",
          'of IDs/groups)'
        ) do |values|
          values.each { |value| registry.omit(value.strip) }
        end

        opts.on(
          '-q',
          '--quiet',
          'Suppress all inessential output'
        ) do
          @verbosity = :quiet
        end

        opts.on(
          '-v',
          '--verbose',
          'Enable verbose logging'
        ) do
          @verbosity = :verbose
        end

        opts.on(
          '-V',
          '--version',
          'Display the version and exit'
        ) do
          @action = :version
        end
      end

      @parser.parse!(args)
    end
  end
end