/*
 *  Copyright (C) 2025 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 *
*/

/*
Example CHPL Atom Layout:
Offset | Field Name         | Hex Bytes (grouped for clarity)
-------------------------------------------------------------
  0    | Atom size          | 00 00 07 DB (big endian = 2011 bytes)
  4    | Atom identifier    | 63 68 70 6C (c h p l)
  8    | Version            | 01
  9    | Flags              | 00 00 00
 12    | Timebase           | 00 00 00 00
 16    | Chapter Count      | 53 00   (big endian = 83)
 18    | Chapter 1:
 18    | Timestamp          | 00 00 00 00 00 00 00
 25    | Size of title      | 11 (17 bytes - this does NOT include the null terminator)
 26    | Title              | 42 6C 6F 6F 64 6C 65 73 73 .... 6F 00 (null-terminated)
                               B  l  o  o  d  l  e  s  s
 44    | Chapter 2:         | Starts at 26 + 17 + 1 (last offset + size + null terminator)

Full Payload Hex (example):
00 00 07 DB 63 68 70 6C 01 00 00 00 00 00 00 00 53 00 00 00 00 00 00 00 00 11
42 6C 6F 6F 64 6C 65 73 73 20 2D 20 49 6E 74 72 6F 00 <- utf8 null terminated string

Notes:
- Chapter timestamp is in milliseconds for version 0, 100 nanosecond units for version 1 unless
  there is a value in the timebase in which case it will override the default values
- Chapter names are utf-8 null-terminated strings
- Total payload size must match atom size - 8 (header bytes)
- There is little documentation on this, but the format of the chpl atom can be worked out from
  https://github.com/enzo1982/mp4v2/blob/main/src/atom_chpl.cpp
- The example hex is taken from an audiobook containing chpl chapters
- Timestamps generated by this class have been correlated against the timestamps generated from
  FFmpeg when reading the QT chapters and have been confirmed to be the same
  Citation https://github.com/Zeugma440/atldotnet/wiki/Focus-on-Chapter-metadata
*/

#pragma once

#include <chrono>
#include <optional>
#include <stdint.h>
#include <string>
#include <utility>
#include <vector>

class CURL;
namespace XFILE
{
class CFile;
}

struct ChplChapter
{
  std::chrono::milliseconds startPts{0}; // All chapter times are stored as milliseconds
  std::string title;
};

enum class ChplChapterStatus : int
{
  Error = -1,
  Found = 0,
  None = 1
};

constexpr auto chplError = ChplChapterStatus::Error;
constexpr auto chplFound = ChplChapterStatus::Found;
constexpr auto chplNone = ChplChapterStatus::None;

struct ChplChapterResult
{
  ChplChapterStatus status{ChplChapterStatus::None};
  std::optional<std::string> errorMessage; // Error messages are only returned for chplError

  constexpr ChplChapterResult() = default;

  constexpr ChplChapterResult(ChplChapterStatus s) : status{s} {}

  ChplChapterResult(ChplChapterStatus s, std::string msg) : status{s}, errorMessage{std::move(msg)}
  {
  }

  explicit operator bool() const { return status == ChplChapterStatus::Found; }

  bool IsError() const { return status == ChplChapterStatus::Error; }
  bool IsFound() const { return status == ChplChapterStatus::Found; }
  bool IsNone() const { return status == ChplChapterStatus::None; }
};

class CChplChapterReader
{
public:
  /*!
   * @brief Parses MP4 chapter atoms (chpl) from Nero/Ahead encoded files
   * \param url [in] url of the file to be scanned
   * \param chapters [out] vector containing the names and start times of any chapters found
   * \return 1 if no chapters found, 0 on success, -1 on error, optionally returns an error message
   */
  static ChplChapterResult ScanNeroChapters(const CURL& url, std::vector<ChplChapter>& chapters);
};
