// 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 "fxbarcode/cfx_barcode.h"

#include <memory>

#include "fxbarcode/cbc_codabar.h"
#include "fxbarcode/cbc_code128.h"
#include "fxbarcode/cbc_code39.h"
#include "fxbarcode/cbc_codebase.h"
#include "fxbarcode/cbc_datamatrix.h"
#include "fxbarcode/cbc_ean13.h"
#include "fxbarcode/cbc_ean8.h"
#include "fxbarcode/cbc_pdf417i.h"
#include "fxbarcode/cbc_qrcode.h"
#include "fxbarcode/cbc_upca.h"
#include "fxbarcode/utils.h"
#include "third_party/base/ptr_util.h"

namespace {

std::unique_ptr<CBC_CodeBase> CreateBarCodeEngineObject(BC_TYPE type) {
  switch (type) {
    case BC_CODE39:
      return std::make_unique<CBC_Code39>();
    case BC_CODABAR:
      return std::make_unique<CBC_Codabar>();
    case BC_CODE128:
      return std::make_unique<CBC_Code128>(BC_CODE128_B);
    case BC_CODE128_B:
      return std::make_unique<CBC_Code128>(BC_CODE128_B);
    case BC_CODE128_C:
      return std::make_unique<CBC_Code128>(BC_CODE128_C);
    case BC_EAN8:
      return std::make_unique<CBC_EAN8>();
    case BC_UPCA:
      return std::make_unique<CBC_UPCA>();
    case BC_EAN13:
      return std::make_unique<CBC_EAN13>();
    case BC_QR_CODE:
      return std::make_unique<CBC_QRCode>();
    case BC_PDF417:
      return std::make_unique<CBC_PDF417I>();
    case BC_DATAMATRIX:
      return std::make_unique<CBC_DataMatrix>();
    case BC_UNKNOWN:
    default:
      return nullptr;
  }
}

}  // namespace

CFX_Barcode::CFX_Barcode() {}

CFX_Barcode::~CFX_Barcode() = default;

std::unique_ptr<CFX_Barcode> CFX_Barcode::Create(BC_TYPE type) {
  auto barcode = pdfium::WrapUnique(new CFX_Barcode());  // Private ctor.
  barcode->m_pBCEngine = CreateBarCodeEngineObject(type);
  return barcode;
}

BC_TYPE CFX_Barcode::GetType() {
  return m_pBCEngine ? m_pBCEngine->GetType() : BC_UNKNOWN;
}

bool CFX_Barcode::SetCharEncoding(BC_CHAR_ENCODING encoding) {
  return m_pBCEngine && m_pBCEngine->SetCharEncoding(encoding);
}

bool CFX_Barcode::SetModuleHeight(int32_t moduleHeight) {
  return m_pBCEngine && m_pBCEngine->SetModuleHeight(moduleHeight);
}

bool CFX_Barcode::SetModuleWidth(int32_t moduleWidth) {
  return m_pBCEngine && m_pBCEngine->SetModuleWidth(moduleWidth);
}

bool CFX_Barcode::SetHeight(int32_t height) {
  return m_pBCEngine && m_pBCEngine->SetHeight(height);
}

bool CFX_Barcode::SetWidth(int32_t width) {
  return m_pBCEngine && m_pBCEngine->SetWidth(width);
}

bool CFX_Barcode::SetPrintChecksum(bool checksum) {
  switch (GetType()) {
    case BC_CODE39:
    case BC_CODABAR:
    case BC_CODE128:
    case BC_CODE128_B:
    case BC_CODE128_C:
    case BC_EAN8:
    case BC_EAN13:
    case BC_UPCA:
      return m_pBCEngine ? (static_cast<CBC_OneCode*>(m_pBCEngine.get())
                                ->SetPrintChecksum(checksum),
                            true)
                         : false;
    default:
      return false;
  }
}

bool CFX_Barcode::SetDataLength(int32_t length) {
  switch (GetType()) {
    case BC_CODE39:
    case BC_CODABAR:
    case BC_CODE128:
    case BC_CODE128_B:
    case BC_CODE128_C:
    case BC_EAN8:
    case BC_EAN13:
    case BC_UPCA:
      return m_pBCEngine ? (static_cast<CBC_OneCode*>(m_pBCEngine.get())
                                ->SetDataLength(length),
                            true)
                         : false;
    default:
      return false;
  }
}

bool CFX_Barcode::SetCalChecksum(bool state) {
  switch (GetType()) {
    case BC_CODE39:
    case BC_CODABAR:
    case BC_CODE128:
    case BC_CODE128_B:
    case BC_CODE128_C:
    case BC_EAN8:
    case BC_EAN13:
    case BC_UPCA:
      return m_pBCEngine ? (static_cast<CBC_OneCode*>(m_pBCEngine.get())
                                ->SetCalChecksum(state),
                            true)
                         : false;
    default:
      return false;
  }
}

bool CFX_Barcode::SetFont(CFX_Font* pFont) {
  switch (GetType()) {
    case BC_CODE39:
    case BC_CODABAR:
    case BC_CODE128:
    case BC_CODE128_B:
    case BC_CODE128_C:
    case BC_EAN8:
    case BC_EAN13:
    case BC_UPCA:
      return m_pBCEngine
                 ? static_cast<CBC_OneCode*>(m_pBCEngine.get())->SetFont(pFont)
                 : false;
    default:
      return false;
  }
}

bool CFX_Barcode::SetFontSize(float size) {
  switch (GetType()) {
    case BC_CODE39:
    case BC_CODABAR:
    case BC_CODE128:
    case BC_CODE128_B:
    case BC_CODE128_C:
    case BC_EAN8:
    case BC_EAN13:
    case BC_UPCA:
      return m_pBCEngine ? (static_cast<CBC_OneCode*>(m_pBCEngine.get())
                                ->SetFontSize(size),
                            true)
                         : false;
    default:
      return false;
  }
}

bool CFX_Barcode::SetFontColor(FX_ARGB color) {
  switch (GetType()) {
    case BC_CODE39:
    case BC_CODABAR:
    case BC_CODE128:
    case BC_CODE128_B:
    case BC_CODE128_C:
    case BC_EAN8:
    case BC_EAN13:
    case BC_UPCA:
      return m_pBCEngine ? (static_cast<CBC_OneCode*>(m_pBCEngine.get())
                                ->SetFontColor(color),
                            true)
                         : false;
    default:
      return false;
  }
}

bool CFX_Barcode::SetTextLocation(BC_TEXT_LOC location) {
  return m_pBCEngine && m_pBCEngine->SetTextLocation(location);
}

bool CFX_Barcode::SetWideNarrowRatio(int8_t ratio) {
  return m_pBCEngine && m_pBCEngine->SetWideNarrowRatio(ratio);
}

bool CFX_Barcode::SetStartChar(char start) {
  return m_pBCEngine && m_pBCEngine->SetStartChar(start);
}

bool CFX_Barcode::SetEndChar(char end) {
  return m_pBCEngine && m_pBCEngine->SetEndChar(end);
}

bool CFX_Barcode::SetErrorCorrectionLevel(int32_t level) {
  return m_pBCEngine && m_pBCEngine->SetErrorCorrectionLevel(level);
}

bool CFX_Barcode::Encode(WideStringView contents) {
  return m_pBCEngine && m_pBCEngine->Encode(contents);
}

bool CFX_Barcode::RenderDevice(CFX_RenderDevice* device,
                               const CFX_Matrix* matrix) {
  return m_pBCEngine && m_pBCEngine->RenderDevice(device, matrix);
}
