// 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();
};

// 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;

  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");
  }
};

// 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_
