# typed: true
# frozen_string_literal: true

module Bhook
  class ArgsParser
    extend T::Sig

    Options = Struct.new(:source, :output, :watch, :verbose, :theme, :generate_theme, :benchmark, :mount, :help)

    def initialize(argv)
      @args = Options.new(nil, nil, false, false, Bhook::THEME_DIR_PATH, nil, false, nil, false)
      @argv = argv.clone
      @opt_parser = build_opt_parser
    end

    def parse
      if (mount = detect_and_read_mount_args_from_config_in_pwd)
        @args.mount = mount
      end

      begin
        @opt_parser.parse(@argv)
        if generate_theme_missing? && help_missing? &&
           source_or_output_paths_missing? && mount_config_missing?
          raise OptionParser::MissingArgument, 'See --help.'
        end
      rescue OptionParser::ParseError => e
        puts "\nError! #{e.message}\n"
        return nil
      end
      @args
    end

    def help_text
      @opt_parser.to_s
    end

    private

    def detect_and_read_mount_args_from_config_in_pwd
      bhook_config_path = File.join(Dir.pwd, Config::BHOOK_CONFIG_FILE)
      return unless File.exist?(bhook_config_path)

      YAML.safe_load(File.read(bhook_config_path))['mount']
    end

    def mount_config_missing?
      !@args.mount
    end

    def help_missing?
      !@args.help
    end

    def source_or_output_paths_missing?
      !@args.source || !@args.output
    end

    def generate_theme_missing?
      !@args.generate_theme
    end

    def build_opt_parser
      OptionParser.new do |opts|
        opts.banner = 'Usage: bhook --source /source/path --output /output/path'

        opts.on('-sSOURCE', '--source=SOURCE',
                String, 'Path to version controlled directory containing source md files') do |source_path|
          @args.source = source_path
        end

        opts.on('-oOUTPUT', '--output=OUTPUT',
                String, 'Path to directory where output files are to be generated') do |out_path|
          @args.output = out_path
        end

        opts.on('-w', '--watch',
                FalseClass,
                'Continuously watch the source directory for changes and generate output') do
          @args.watch = true
        end

        opts.on('-v', '--verbose',
                FalseClass,
                'Print detailed information about files as they are processed') do
          @args.verbose = true
        end

        opts.on('-tPATH', '--theme=PATH',
                String,
                'Path to directory containing theme files to use when generating html') do |path|
          @args.theme = path
        end

        opts.on('--generate-theme=PATH',
                String,
                'Generate a baseline theme that you can then modify to your needs') do |path|
          @args.generate_theme = path
        end

        opts.on('--benchmark',
                FalseClass,
                'Run a performance benchmark for the specified source') do
          @args.benchmark = true
        end

        opts.on('-h', '--help', FalseClass, 'Prints this help') do |_help|
          @args.help = true
        end
      end
    end
  end
end