// Copyright 2018 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/cbc_eancode.h"

#include <utility>

#include "core/fxcrt/fx_memory_wrappers.h"
#include "fxbarcode/oned/BC_OnedEANWriter.h"

CBC_EANCode::CBC_EANCode(std::unique_ptr<CBC_OneDimEANWriter> pWriter)
    : CBC_OneCode(std::move(pWriter)) {}

CBC_EANCode::~CBC_EANCode() = default;

CBC_OneDimEANWriter* CBC_EANCode::GetOneDimEANWriter() {
  return static_cast<CBC_OneDimEANWriter*>(m_pBCWriter.get());
}

bool CBC_EANCode::Encode(WideStringView contents) {
  if (contents.IsEmpty() || contents.GetLength() > kMaxInputLengthBytes)
    return false;

  BCFORMAT format = GetFormat();
  int32_t out_width = 0;
  int32_t out_height = 0;
  m_renderContents = Preprocess(contents);
  ByteString str = m_renderContents.ToUTF8();
  auto* pWriter = GetOneDimEANWriter();
  pWriter->InitEANWriter();
  std::unique_ptr<uint8_t, FxFreeDeleter> data(
      pWriter->Encode(str, format, out_width, out_height));
  return data && pWriter->RenderResult(m_renderContents.AsStringView(),
                                       data.get(), out_width);
}

bool CBC_EANCode::RenderDevice(CFX_RenderDevice* device,
                               const CFX_Matrix* matrix) {
  return GetOneDimEANWriter()->RenderDeviceResult(
      device, matrix, m_renderContents.AsStringView());
}

WideString CBC_EANCode::Preprocess(WideStringView contents) {
  auto* pWriter = GetOneDimEANWriter();
  WideString encoded_contents = pWriter->FilterContents(contents);
  size_t length = encoded_contents.GetLength();
  size_t max_length = GetMaxLength();
  if (length <= max_length) {
    for (size_t i = 0; i < max_length - length; i++)
      encoded_contents.InsertAtFront(L'0');

    ByteString str = encoded_contents.ToUTF8();
    int32_t checksum = pWriter->CalcChecksum(str);
    str += '0' + checksum;
    encoded_contents = WideString::FromUTF8(str.AsStringView());
  } else {
    encoded_contents = encoded_contents.First(max_length + 1);
  }

  return encoded_contents;
}
