// Copyright 2023 Google LLC
// SPDX-License-Identifier: BSD-2-Clause

#ifndef LIBAVIF_APPS_AVIFGAINMAPUTIL_PROGRAM_COMMAND_H_
#define LIBAVIF_APPS_AVIFGAINMAPUTIL_PROGRAM_COMMAND_H_

#include <string>

#include "argparse.hpp"
#include "avif/avif.h"

namespace avif {

// A command that can be invoked by name (similar to how 'git' has commands like
// 'commit', 'checkout', etc.)
// NOTE: "avifgainmaputil" is currently hardcoded in the implementation (for
// help messages).
class ProgramCommand {
 public:
  // 'name' is the command that should be used to invoke the command on the
  // command line.
  // 'short_description' should be a one line description of what the command
  // does.
  ProgramCommand(const std::string& name, const std::string& short_description,
                 const std::string& long_description = "");

  virtual ~ProgramCommand() = default;

  // Parses command line arguments. Should be called before Run().
  avifResult ParseArgs(int argc, const char* const argv[]);

  // Runs the command.
  virtual avifResult Run() = 0;

  std::string name() const { return name_; }
  std::string short_description() const { return short_description_; }

  // Prints this command's help on stdout.
  void PrintUsage();

 protected:
  argparse::ArgumentParser argparse_;

 private:
  std::string name_;
  std::string short_description_;
};

//------------------------------------------------------------------------------
// Utilities for flag parsing.

// avifPixelFormat converter for use with argparse.
// Actually converts to int, converting to avifPixelFormat didn't seem to
// compile.
struct PixelFormatConverter {
  // Methods expected by argparse.
  argparse::ConvertedValue<int> from_str(const std::string& str);
  std::vector<std::string> default_choices();
};

struct CicpValues {
  avifColorPrimaries color_primaries;
  avifTransferCharacteristics transfer_characteristics;
  avifMatrixCoefficients matrix_coefficients;
};

// CicpValues converter for use with argparse. Parses the format 'P/T/M'.
struct CicpConverter {
  // Methods expected by argparse.
  argparse::ConvertedValue<CicpValues> from_str(const std::string& str);
  std::vector<std::string> default_choices();
};

// avifContentLightLevelInformationBox converter for use with argparse.
// Parses the format 'maxCLL,maxPALL'.
struct ClliConverter {
  // Methods expected by argparse.
  argparse::ConvertedValue<avifContentLightLevelInformationBox> from_str(
      const std::string& str);
  std::vector<std::string> default_choices();
};

struct GridOptions {
  int grid_cols = 0;
  int grid_rows = 0;
};

// GridOptions converter for use with argparse. Parses the format 'MxN'.
struct GridOptionsConverter {
  // Methods expected by argparse.
  argparse::ConvertedValue<GridOptions> from_str(const std::string& str);
  std::vector<std::string> default_choices();
};

// Jobs converter for use with argparse. Parses an integer or "all".
struct JobsConverter {
  // Methods expected by argparse.
  argparse::ConvertedValue<int> from_str(const std::string& str);
  std::vector<std::string> default_choices();
};

// Basic flags for image writing.
struct BasicImageEncodeArgs {
  argparse::ArgValue<int> speed;
  argparse::ArgValue<int> quality;
  argparse::ArgValue<int> quality_alpha;
  argparse::ArgValue<GridOptions> grid;

  // can_have_alpha should be true if the image can have alpha and the
  // output format can be avif.
  void Init(argparse::ArgumentParser& argparse, bool can_have_alpha) {
    argparse.add_argument(speed, "--speed", "-s")
        .help("Encoder speed (0-10, slowest-fastest)")
        .default_value("6");
    argparse.add_argument(quality, "--qcolor", "-q")
        .help((can_have_alpha
                   ? "Quality for color (0-100, where 100 is lossless)"
                   : "Quality (0-100, where 100 is lossless)"))
        .default_value("60");
    if (can_have_alpha) {
      argparse.add_argument(quality_alpha, "--qalpha")
          .help("Quality for alpha (0-100, where 100 is lossless)")
          .default_value("100");
    }
    argparse.add_argument<GridOptions, GridOptionsConverter>(grid, "--grid")
        .help("Encode a grid AVIF with M cols and N rows, expressed as MxN")
        .default_value("1x1");
  }
};

// Flags relevant when reading jpeg/png.
struct ImageReadArgs {
  argparse::ArgValue<int> depth;
  argparse::ArgValue<int> pixel_format;
  argparse::ArgValue<bool> ignore_profile;
  argparse::ArgValue<bool> ignore_alpha;

  void Init(argparse::ArgumentParser& argparse) {
    argparse
        .add_argument<int, PixelFormatConverter>(pixel_format, "--yuv", "-y")
        .help("Output YUV format for avif (default = automatic)");
    argparse.add_argument(depth, "--depth", "-d")
        .choices({"0", "8", "10", "12"})
        .help("Output depth (0 = automatic)");
    argparse.add_argument(ignore_profile, "--ignore-profile")
        .help(
            "If the input file contains an embedded color profile, ignore it "
            "(no-op if absent)")
        .action(argparse::Action::STORE_TRUE)
        .default_value("false");
    argparse.add_argument(ignore_alpha, "--ignore-alpha")
        .help(
            "If the input file contains an alpha channel, ignore it "
            "(no-op if absent)")
        .action(argparse::Action::STORE_TRUE)
        .default_value("false");
  }
};

// Flags for setting the number of worker threads.
struct JobsArgs {
  argparse::ArgValue<int> jobs;

  void Init(argparse::ArgumentParser& argparse) {
    argparse.add_argument<int, JobsConverter>(jobs, "--jobs", "-j")
        .help(
            "Number of jobs (worker threads), or 'all' to potentially use as "
            "many cores as possible.")
        .default_value("all");
  }
};

// Helper to parse flags that contain several delimited values.
template <typename T>
bool ParseList(std::string to_parse, char delim, int expected_num,
               std::vector<T>* out) {
  std::stringstream ss(to_parse);
  std::string part;
  T parsed;
  while (std::getline(ss, part, delim)) {
    std::istringstream is(part);
    is >> parsed;
    if (is.bad()) {
      return false;
    }
    out->push_back(parsed);
  }
  if (expected_num > 0 && (int)out->size() != expected_num) {
    return false;
  }
  return true;
}

}  // namespace avif

#endif  // LIBAVIF_APPS_AVIFGAINMAPUTIL_PROGRAM_COMMAND_H_
