// Copyright 2017 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 "xfa/fxfa/parser/cxfa_barcode.h"

#include <memory>

#include "fxjs/xfa/cjx_node.h"
#include "xfa/fxfa/parser/cxfa_measurement.h"

namespace {

const CXFA_Node::AttributeData kBarcodeAttributeData[] = {
    {XFA_Attribute::Id, XFA_AttributeType::CData, nullptr},
    {XFA_Attribute::DataRowCount, XFA_AttributeType::CData, nullptr},
    {XFA_Attribute::Use, XFA_AttributeType::CData, nullptr},
    {XFA_Attribute::DataPrep, XFA_AttributeType::Enum,
     (void*)XFA_AttributeValue::None},
    {XFA_Attribute::Type, XFA_AttributeType::CData, (void*)nullptr},
    {XFA_Attribute::TextLocation, XFA_AttributeType::Enum,
     (void*)XFA_AttributeValue::Below},
    {XFA_Attribute::ModuleWidth, XFA_AttributeType::Measure, (void*)L"0.25mm"},
    {XFA_Attribute::PrintCheckDigit, XFA_AttributeType::Boolean, (void*)0},
    {XFA_Attribute::ModuleHeight, XFA_AttributeType::Measure, (void*)L"5mm"},
    {XFA_Attribute::StartChar, XFA_AttributeType::CData, nullptr},
    {XFA_Attribute::Truncate, XFA_AttributeType::Boolean, (void*)0},
    {XFA_Attribute::WideNarrowRatio, XFA_AttributeType::CData, (void*)L"3:1"},
    {XFA_Attribute::ErrorCorrectionLevel, XFA_AttributeType::CData, nullptr},
    {XFA_Attribute::UpsMode, XFA_AttributeType::Enum,
     (void*)XFA_AttributeValue::UsCarrier},
    {XFA_Attribute::Checksum, XFA_AttributeType::Enum,
     (void*)XFA_AttributeValue::None},
    {XFA_Attribute::CharEncoding, XFA_AttributeType::CData, (void*)L"UTF-8"},
    {XFA_Attribute::Usehref, XFA_AttributeType::CData, nullptr},
    {XFA_Attribute::DataColumnCount, XFA_AttributeType::CData, nullptr},
    {XFA_Attribute::RowColumnRatio, XFA_AttributeType::CData, nullptr},
    {XFA_Attribute::DataLength, XFA_AttributeType::CData, nullptr},
    {XFA_Attribute::EndChar, XFA_AttributeType::CData, nullptr},
};

}  // namespace

CXFA_Barcode::CXFA_Barcode(CXFA_Document* doc, XFA_PacketType packet)
    : CXFA_Node(doc,
                packet,
                (XFA_XDPPACKET_Template | XFA_XDPPACKET_Form),
                XFA_ObjectType::Node,
                XFA_Element::Barcode,
                {},
                kBarcodeAttributeData,
                std::make_unique<CJX_Node>(this)) {}

CXFA_Barcode::~CXFA_Barcode() = default;

XFA_FFWidgetType CXFA_Barcode::GetDefaultFFWidgetType() const {
  return XFA_FFWidgetType::kBarcode;
}

WideString CXFA_Barcode::GetBarcodeType() {
  return WideString(JSObject()->GetCData(XFA_Attribute::Type));
}

Optional<WideString> CXFA_Barcode::GetCharEncoding() {
  return JSObject()->TryCData(XFA_Attribute::CharEncoding, true);
}

Optional<bool> CXFA_Barcode::GetChecksum() {
  Optional<XFA_AttributeValue> checksum =
      JSObject()->TryEnum(XFA_Attribute::Checksum, true);
  if (!checksum)
    return {};

  switch (*checksum) {
    case XFA_AttributeValue::None:
      return {false};
    case XFA_AttributeValue::Auto:
      return {true};
    case XFA_AttributeValue::Checksum_1mod10:
    case XFA_AttributeValue::Checksum_1mod10_1mod11:
    case XFA_AttributeValue::Checksum_2mod10:
    default:
      break;
  }
  return {};
}

Optional<int32_t> CXFA_Barcode::GetDataLength() {
  Optional<WideString> wsDataLength =
      JSObject()->TryCData(XFA_Attribute::DataLength, true);
  if (!wsDataLength)
    return {};

  return {FXSYS_wtoi(wsDataLength->c_str())};
}

Optional<char> CXFA_Barcode::GetStartChar() {
  Optional<WideString> wsStartEndChar =
      JSObject()->TryCData(XFA_Attribute::StartChar, true);
  if (!wsStartEndChar || wsStartEndChar->IsEmpty())
    return {};

  return {static_cast<char>((*wsStartEndChar)[0])};
}

Optional<char> CXFA_Barcode::GetEndChar() {
  Optional<WideString> wsStartEndChar =
      JSObject()->TryCData(XFA_Attribute::EndChar, true);
  if (!wsStartEndChar || wsStartEndChar->IsEmpty())
    return {};

  return {static_cast<char>((*wsStartEndChar)[0])};
}

Optional<int32_t> CXFA_Barcode::GetECLevel() {
  Optional<WideString> wsECLevel =
      JSObject()->TryCData(XFA_Attribute::ErrorCorrectionLevel, true);
  if (!wsECLevel)
    return {};
  return {FXSYS_wtoi(wsECLevel->c_str())};
}

Optional<int32_t> CXFA_Barcode::GetModuleWidth() {
  Optional<CXFA_Measurement> moduleWidthHeight =
      JSObject()->TryMeasure(XFA_Attribute::ModuleWidth, true);
  if (!moduleWidthHeight)
    return {};

  return {static_cast<int32_t>(moduleWidthHeight->ToUnit(XFA_Unit::Pt))};
}

Optional<int32_t> CXFA_Barcode::GetModuleHeight() {
  Optional<CXFA_Measurement> moduleWidthHeight =
      JSObject()->TryMeasure(XFA_Attribute::ModuleHeight, true);
  if (!moduleWidthHeight)
    return {};

  return {static_cast<int32_t>(moduleWidthHeight->ToUnit(XFA_Unit::Pt))};
}

Optional<bool> CXFA_Barcode::GetPrintChecksum() {
  return JSObject()->TryBoolean(XFA_Attribute::PrintCheckDigit, true);
}

Optional<XFA_AttributeValue> CXFA_Barcode::GetTextLocation() {
  return JSObject()->TryEnum(XFA_Attribute::TextLocation, true);
}

Optional<bool> CXFA_Barcode::GetTruncate() {
  return JSObject()->TryBoolean(XFA_Attribute::Truncate, true);
}

Optional<int8_t> CXFA_Barcode::GetWideNarrowRatio() {
  Optional<WideString> wsWideNarrowRatio =
      JSObject()->TryCData(XFA_Attribute::WideNarrowRatio, true);
  if (!wsWideNarrowRatio)
    return {};

  Optional<size_t> ptPos = wsWideNarrowRatio->Find(':');
  if (!ptPos)
    return {static_cast<int8_t>(FXSYS_wtoi(wsWideNarrowRatio->c_str()))};

  int32_t fB = FXSYS_wtoi(
      wsWideNarrowRatio->Last(wsWideNarrowRatio->GetLength() - (*ptPos + 1))
          .c_str());
  if (!fB)
    return {0};

  int32_t fA = FXSYS_wtoi(wsWideNarrowRatio->First(*ptPos).c_str());
  float result = static_cast<float>(fA) / static_cast<float>(fB);
  return {static_cast<int8_t>(result)};
}
