// Copyright 2014 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 "xfa/fwl/cfwl_barcode.h"

#include "fxbarcode/cfx_barcode.h"
#include "xfa/fgas/font/cfgas_gefont.h"
#include "xfa/fwl/cfwl_notedriver.h"
#include "xfa/fwl/cfwl_themepart.h"
#include "xfa/fwl/ifwl_themeprovider.h"
#include "xfa/fwl/theme/cfwl_utils.h"

CFWL_Barcode::CFWL_Barcode(CFWL_App* app)
    : CFWL_Edit(app, Properties(), nullptr) {}

CFWL_Barcode::~CFWL_Barcode() = default;

FWL_Type CFWL_Barcode::GetClassID() const {
  return FWL_Type::Barcode;
}

void CFWL_Barcode::Update() {
  if (IsLocked())
    return;

  CFWL_Edit::Update();
  GenerateBarcodeImageCache();
}

void CFWL_Barcode::DrawWidget(CFGAS_GEGraphics* pGraphics,
                              const CFX_Matrix& matrix) {
  if (!pGraphics)
    return;

  if ((m_Properties.m_dwStates & FWL_STATE_WGT_Focused) == 0) {
    GenerateBarcodeImageCache();
    if (!m_pBarcodeEngine || m_eStatus != Status::kEncodeSuccess)
      return;

    CFX_Matrix mt;
    mt.e = GetRTClient().left;
    mt.f = GetRTClient().top;
    mt.Concat(matrix);

    // TODO(tsepez): Curious as to why |mt| is unused?
    m_pBarcodeEngine->RenderDevice(pGraphics->GetRenderDevice(), matrix);
    return;
  }
  CFWL_Edit::DrawWidget(pGraphics, matrix);
}

void CFWL_Barcode::SetType(BC_TYPE type) {
  if (m_type == type)
    return;

  m_pBarcodeEngine.reset();
  m_type = type;
  m_eStatus = Status::kNeedUpdate;
}

void CFWL_Barcode::SetText(const WideString& wsText) {
  m_pBarcodeEngine.reset();
  m_eStatus = Status::kNeedUpdate;
  CFWL_Edit::SetText(wsText);
}

void CFWL_Barcode::SetTextSkipNotify(const WideString& wsText) {
  m_pBarcodeEngine.reset();
  m_eStatus = Status::kNeedUpdate;
  CFWL_Edit::SetTextSkipNotify(wsText);
}

bool CFWL_Barcode::IsProtectedType() const {
  if (!m_pBarcodeEngine)
    return true;

  BC_TYPE tEngineType = m_pBarcodeEngine->GetType();
  return tEngineType == BC_TYPE::kQRCode || tEngineType == BC_TYPE::kPDF417 ||
         tEngineType == BC_TYPE::kDataMatrix;
}

void CFWL_Barcode::OnProcessEvent(CFWL_Event* pEvent) {
  if (pEvent->GetType() == CFWL_Event::Type::TextWillChange) {
    m_pBarcodeEngine.reset();
    m_eStatus = Status::kNeedUpdate;
  }
  CFWL_Edit::OnProcessEvent(pEvent);
}

void CFWL_Barcode::SetCharEncoding(BC_CHAR_ENCODING encoding) {
  m_eCharEncoding = encoding;
}

void CFWL_Barcode::SetModuleHeight(int32_t height) {
  m_nModuleHeight = height;
}

void CFWL_Barcode::SetModuleWidth(int32_t width) {
  m_nModuleWidth = width;
}

void CFWL_Barcode::SetDataLength(int32_t dataLength) {
  m_nDataLength = dataLength;
  SetLimit(dataLength);
}

void CFWL_Barcode::SetCalChecksum(bool calChecksum) {
  m_bCalChecksum = calChecksum;
}

void CFWL_Barcode::SetPrintChecksum(bool printChecksum) {
  m_bPrintChecksum = printChecksum;
}

void CFWL_Barcode::SetTextLocation(BC_TEXT_LOC location) {
  m_eTextLocation = location;
}

void CFWL_Barcode::SetWideNarrowRatio(int8_t ratio) {
  m_nWideNarrowRatio = ratio;
}

void CFWL_Barcode::SetStartChar(char startChar) {
  m_cStartChar = startChar;
}

void CFWL_Barcode::SetEndChar(char endChar) {
  m_cEndChar = endChar;
}

void CFWL_Barcode::SetErrorCorrectionLevel(int32_t ecLevel) {
  m_nECLevel = ecLevel;
}

void CFWL_Barcode::GenerateBarcodeImageCache() {
  if (m_eStatus != Status::kNeedUpdate)
    return;

  m_eStatus = Status::kNormal;
  CreateBarcodeEngine();
  if (!m_pBarcodeEngine)
    return;

  IFWL_ThemeProvider* pTheme = GetThemeProvider();
  CFWL_ThemePart part(CFWL_ThemePart::Part::kNone, this);
  if (RetainPtr<CFGAS_GEFont> pFont = pTheme->GetFont(part)) {
    if (CFX_Font* pCXFont = pFont->GetDevFont())
      m_pBarcodeEngine->SetFont(pCXFont);
  }
  m_pBarcodeEngine->SetFontSize(pTheme->GetFontSize(part));
  m_pBarcodeEngine->SetFontColor(pTheme->GetTextColor(part));
  m_pBarcodeEngine->SetHeight(int32_t(GetRTClient().height));
  m_pBarcodeEngine->SetWidth(int32_t(GetRTClient().width));
  if (m_eCharEncoding.has_value())
    m_pBarcodeEngine->SetCharEncoding(m_eCharEncoding.value());
  if (m_nModuleHeight.has_value())
    m_pBarcodeEngine->SetModuleHeight(m_nModuleHeight.value());
  if (m_nModuleWidth.has_value())
    m_pBarcodeEngine->SetModuleWidth(m_nModuleWidth.value());
  if (m_nDataLength.has_value())
    m_pBarcodeEngine->SetDataLength(m_nDataLength.value());
  if (m_bCalChecksum.has_value())
    m_pBarcodeEngine->SetCalChecksum(m_bCalChecksum.value());
  if (m_bPrintChecksum.has_value())
    m_pBarcodeEngine->SetPrintChecksum(m_bPrintChecksum.value());
  if (m_eTextLocation.has_value())
    m_pBarcodeEngine->SetTextLocation(m_eTextLocation.value());
  if (m_nWideNarrowRatio.has_value())
    m_pBarcodeEngine->SetWideNarrowRatio(m_nWideNarrowRatio.value());
  if (m_cStartChar.has_value())
    m_pBarcodeEngine->SetStartChar(m_cStartChar.value());
  if (m_cEndChar.has_value())
    m_pBarcodeEngine->SetEndChar(m_cEndChar.value());
  if (m_nECLevel.has_value())
    m_pBarcodeEngine->SetErrorCorrectionLevel(m_nECLevel.value());

  m_eStatus = m_pBarcodeEngine->Encode(GetText().AsStringView())
                  ? Status::kEncodeSuccess
                  : Status::kNormal;
}

void CFWL_Barcode::CreateBarcodeEngine() {
  if (m_pBarcodeEngine || m_type == BC_TYPE::kUnknown)
    return;

  m_pBarcodeEngine = CFX_Barcode::Create(m_type);
}
