// Copyright 2014 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 "fpdfsdk/pwl/cpwl_icon.h"

#include <algorithm>
#include <sstream>

#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
#include "fpdfsdk/pwl/cpwl_wnd.h"

CPWL_Icon::CPWL_Icon() : m_pPDFStream(nullptr), m_pIconFit(nullptr) {}

CPWL_Icon::~CPWL_Icon() {}

std::pair<float, float> CPWL_Icon::GetImageSize() {
  if (!m_pPDFStream)
    return {0.0f, 0.0f};

  CPDF_Dictionary* pDict = m_pPDFStream->GetDict();
  if (!pDict)
    return {0.0f, 0.0f};

  CFX_FloatRect rect = pDict->GetRectFor("BBox");
  return {rect.right - rect.left, rect.top - rect.bottom};
}

CFX_Matrix CPWL_Icon::GetImageMatrix() {
  if (!m_pPDFStream)
    return CFX_Matrix();
  if (CPDF_Dictionary* pDict = m_pPDFStream->GetDict())
    return pDict->GetMatrixFor("Matrix");
  return CFX_Matrix();
}

ByteString CPWL_Icon::GetImageAlias() {
  if (!m_pPDFStream)
    return ByteString();
  if (CPDF_Dictionary* pDict = m_pPDFStream->GetDict())
    return pDict->GetStringFor("Name");
  return ByteString();
}

std::pair<float, float> CPWL_Icon::GetIconPosition() {
  if (!m_pIconFit)
    return {0.0f, 0.0f};

  CPDF_Array* pA =
      m_pIconFit->GetDict() ? m_pIconFit->GetDict()->GetArrayFor("A") : nullptr;
  if (!pA)
    return {0.0f, 0.0f};

  size_t dwCount = pA->GetCount();
  return {dwCount > 0 ? pA->GetNumberAt(0) : 0.0f,
          dwCount > 1 ? pA->GetNumberAt(1) : 0.0f};
}

std::pair<float, float> CPWL_Icon::GetScale() {
  float fHScale = 1.0f;
  float fVScale = 1.0f;

  if (!m_pPDFStream)
    return {fHScale, fVScale};

  CFX_FloatRect rcPlate = GetClientRect();
  float fPlateWidth = rcPlate.right - rcPlate.left;
  float fPlateHeight = rcPlate.top - rcPlate.bottom;

  float fImageWidth;
  float fImageHeight;
  std::tie(fImageWidth, fImageHeight) = GetImageSize();

  int32_t nScaleMethod = m_pIconFit ? m_pIconFit->GetScaleMethod() : 0;

  switch (nScaleMethod) {
    default:
    case 0:
      fHScale = fPlateWidth / std::max(fImageWidth, 1.0f);
      fVScale = fPlateHeight / std::max(fImageHeight, 1.0f);
      break;
    case 1:
      if (fPlateWidth < fImageWidth)
        fHScale = fPlateWidth / std::max(fImageWidth, 1.0f);
      if (fPlateHeight < fImageHeight)
        fVScale = fPlateHeight / std::max(fImageHeight, 1.0f);
      break;
    case 2:
      if (fPlateWidth > fImageWidth)
        fHScale = fPlateWidth / std::max(fImageWidth, 1.0f);
      if (fPlateHeight > fImageHeight)
        fVScale = fPlateHeight / std::max(fImageHeight, 1.0f);
      break;
    case 3:
      break;
  }

  float fMinScale;
  if (m_pIconFit && m_pIconFit->IsProportionalScale()) {
    fMinScale = std::min(fHScale, fVScale);
    fHScale = fMinScale;
    fVScale = fMinScale;
  }
  return {fHScale, fVScale};
}

std::pair<float, float> CPWL_Icon::GetImageOffset() {
  float fLeft;
  float fBottom;
  std::tie(fLeft, fBottom) = GetIconPosition();

  float fImageWidth;
  float fImageHeight;
  std::tie(fImageWidth, fImageHeight) = GetImageSize();

  float fHScale, fVScale;
  std::tie(fHScale, fVScale) = GetScale();

  float fImageFactWidth = fImageWidth * fHScale;
  float fImageFactHeight = fImageHeight * fVScale;

  CFX_FloatRect rcPlate = GetClientRect();
  float fPlateWidth = rcPlate.right - rcPlate.left;
  float fPlateHeight = rcPlate.top - rcPlate.bottom;

  return {(fPlateWidth - fImageFactWidth) * fLeft,
          (fPlateHeight - fImageFactHeight) * fBottom};
}
