// Copyright 2016 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "core/fpdfdoc/cpdf_defaultappearance.h"

#include <algorithm>
#include <vector>

#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_simple_parser.h"
#include "core/fpdfapi/parser/fpdf_parser_utility.h"
#include "core/fpdfdoc/cpdf_formfield.h"
#include "core/fxcrt/fx_string.h"
#include "core/fxcrt/notreached.h"
#include "core/fxge/cfx_color.h"

namespace {

ByteString GetDefaultAppearanceString(const CPDF_Dictionary* annot_dict,
                                      const CPDF_Dictionary* acroform_dict) {
  ByteString default_appearance_string;
  RetainPtr<const CPDF_Object> default_appearance_object =
      CPDF_FormField::GetFieldAttrForDict(annot_dict, "DA");
  if (default_appearance_object) {
    default_appearance_string = default_appearance_object->GetString();
  }
  if (default_appearance_string.IsEmpty()) {
    default_appearance_string = acroform_dict->GetByteStringFor("DA");
  }
  return default_appearance_string;
}

// Find the token and its |nParams| parameters from the start of data,
// and move the current position to the start of those parameters.
bool FindTagParamFromStart(CPDF_SimpleParser* parser,
                           ByteStringView token,
                           int nParams) {
  nParams++;

  std::vector<uint32_t> pBuf(nParams);
  int buf_index = 0;
  int buf_count = 0;

  parser->SetCurrentPosition(0);
  while (true) {
    pBuf[buf_index++] = parser->GetCurrentPosition();
    if (buf_index == nParams) {
      buf_index = 0;
    }

    buf_count++;
    if (buf_count > nParams) {
      buf_count = nParams;
    }

    ByteStringView word = parser->GetWord();
    if (word.IsEmpty()) {
      return false;
    }

    if (word == token) {
      if (buf_count < nParams) {
        continue;
      }

      parser->SetCurrentPosition(pBuf[buf_index]);
      return true;
    }
  }
}

}  // namespace

CPDF_DefaultAppearance::CPDF_DefaultAppearance(const ByteString& csDA)
    : da_(csDA) {}

CPDF_DefaultAppearance::CPDF_DefaultAppearance(
    const CPDF_Dictionary* annot_dict,
    const CPDF_Dictionary* acroform_dict)
    : CPDF_DefaultAppearance(
          GetDefaultAppearanceString(annot_dict, acroform_dict)) {}

CPDF_DefaultAppearance::~CPDF_DefaultAppearance() = default;

std::optional<CPDF_DefaultAppearance::FontNameAndSize>
CPDF_DefaultAppearance::GetFont() const {
  if (da_.IsEmpty()) {
    return std::nullopt;
  }

  CPDF_SimpleParser syntax(da_.AsStringView().unsigned_span());
  if (!FindTagParamFromStart(&syntax, "Tf", 2)) {
    return FontNameAndSize();
  }

  // Deliberately using separate statements here to ensure the correct
  // evaluation order.
  FontNameAndSize result;
  result.name = PDF_NameDecode(syntax.GetWord().Substr(1));
  result.size = StringToFloat(syntax.GetWord());
  return result;
}

float CPDF_DefaultAppearance::GetFontSizeOrZero() const {
  auto maybe_font_name_and_size = GetFont();
  if (!maybe_font_name_and_size.has_value()) {
    return 0;
  }
  return maybe_font_name_and_size.value().size;
}

std::optional<CFX_Color> CPDF_DefaultAppearance::GetColor() const {
  if (da_.IsEmpty()) {
    return std::nullopt;
  }

  CPDF_SimpleParser syntax(da_.AsStringView().unsigned_span());
  if (FindTagParamFromStart(&syntax, "g", 1)) {
    float gray = StringToFloat(syntax.GetWord());
    return CFX_Color(CFX_Color::Type::kGray, gray);
  }
  if (FindTagParamFromStart(&syntax, "rg", 3)) {
    float r = StringToFloat(syntax.GetWord());
    float g = StringToFloat(syntax.GetWord());
    float b = StringToFloat(syntax.GetWord());
    return CFX_Color(CFX_Color::Type::kRGB, r, g, b);
  }
  if (FindTagParamFromStart(&syntax, "k", 4)) {
    float c = StringToFloat(syntax.GetWord());
    float m = StringToFloat(syntax.GetWord());
    float y = StringToFloat(syntax.GetWord());
    float k = StringToFloat(syntax.GetWord());
    return CFX_Color(CFX_Color::Type::kCMYK, c, m, y, k);
  }
  return std::nullopt;
}

std::optional<CFX_Color::TypeAndARGB> CPDF_DefaultAppearance::GetColorARGB()
    const {
  std::optional<CFX_Color> maybe_color = GetColor();
  if (!maybe_color.has_value()) {
    return std::nullopt;
  }

  const CFX_Color& color = maybe_color.value();
  if (color.nColorType == CFX_Color::Type::kGray) {
    int g = static_cast<int>(color.fColor1 * 255 + 0.5f);
    return CFX_Color::TypeAndARGB(CFX_Color::Type::kGray,
                                  ArgbEncode(255, g, g, g));
  }
  if (color.nColorType == CFX_Color::Type::kRGB) {
    int r = static_cast<int>(color.fColor1 * 255 + 0.5f);
    int g = static_cast<int>(color.fColor2 * 255 + 0.5f);
    int b = static_cast<int>(color.fColor3 * 255 + 0.5f);
    return CFX_Color::TypeAndARGB(CFX_Color::Type::kRGB,
                                  ArgbEncode(255, r, g, b));
  }
  if (color.nColorType == CFX_Color::Type::kCMYK) {
    float r = 1.0f - std::min(1.0f, color.fColor1 + color.fColor4);
    float g = 1.0f - std::min(1.0f, color.fColor2 + color.fColor4);
    float b = 1.0f - std::min(1.0f, color.fColor3 + color.fColor4);
    return CFX_Color::TypeAndARGB(
        CFX_Color::Type::kCMYK,
        ArgbEncode(255, static_cast<int>(r * 255 + 0.5f),
                   static_cast<int>(g * 255 + 0.5f),
                   static_cast<int>(b * 255 + 0.5f)));
  }
  NOTREACHED();
}

// static
bool CPDF_DefaultAppearance::FindTagParamFromStartForTesting(
    CPDF_SimpleParser* parser,
    ByteStringView token,
    int nParams) {
  return FindTagParamFromStart(parser, token, nParams);
}
