// Copyright 2016 PDFium Authors. All rights reserved.
// 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_simple_parser.h"
#include "core/fpdfapi/parser/fpdf_parser_utility.h"
#include "core/fxge/cfx_color.h"
#include "third_party/base/notreached.h"

namespace {

// 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->SetCurPos(0);
  while (1) {
    pBuf[buf_index++] = parser->GetCurPos();
    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->SetCurPos(pBuf[buf_index]);
      return true;
    }
  }
  return false;
}

}  // namespace

CPDF_DefaultAppearance::CPDF_DefaultAppearance() = default;

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

CPDF_DefaultAppearance::CPDF_DefaultAppearance(
    const CPDF_DefaultAppearance& cDA) = default;

CPDF_DefaultAppearance::~CPDF_DefaultAppearance() = default;

Optional<ByteString> CPDF_DefaultAppearance::GetFont(float* fFontSize) {
  *fFontSize = 0.0f;
  if (m_csDA.IsEmpty())
    return pdfium::nullopt;

  ByteString csFontNameTag;
  CPDF_SimpleParser syntax(m_csDA.AsStringView().raw_span());
  if (FindTagParamFromStart(&syntax, "Tf", 2)) {
    csFontNameTag = ByteString(syntax.GetWord());
    csFontNameTag.Delete(0, 1);
    *fFontSize = StringToFloat(syntax.GetWord());
  }
  return PDF_NameDecode(csFontNameTag.AsStringView());
}

Optional<CFX_Color> CPDF_DefaultAppearance::GetColor() const {
  if (m_csDA.IsEmpty())
    return pdfium::nullopt;

  float fc[4];
  CPDF_SimpleParser syntax(m_csDA.AsStringView().raw_span());
  if (FindTagParamFromStart(&syntax, "g", 1)) {
    fc[0] = StringToFloat(syntax.GetWord());
    return CFX_Color(CFX_Color::Type::kGray, fc[0]);
  }
  if (FindTagParamFromStart(&syntax, "rg", 3)) {
    fc[0] = StringToFloat(syntax.GetWord());
    fc[1] = StringToFloat(syntax.GetWord());
    fc[2] = StringToFloat(syntax.GetWord());
    return CFX_Color(CFX_Color::Type::kRGB, fc[0], fc[1], fc[2]);
  }
  if (FindTagParamFromStart(&syntax, "k", 4)) {
    fc[0] = StringToFloat(syntax.GetWord());
    fc[1] = StringToFloat(syntax.GetWord());
    fc[2] = StringToFloat(syntax.GetWord());
    fc[3] = StringToFloat(syntax.GetWord());
    return CFX_Color(CFX_Color::Type::kCMYK, fc[0], fc[1], fc[2], fc[3]);
  }
  return pdfium::nullopt;
}

Optional<CFX_Color::TypeAndARGB> CPDF_DefaultAppearance::GetColorARGB() const {
  Optional<CFX_Color> maybe_color = GetColor();
  if (!maybe_color.has_value())
    return pdfium::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();
  return pdfium::nullopt;
}

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