// 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
// Original code is licensed as follows:
/*
 * Copyright 2006-2007 Jeremias Maerki.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "fxbarcode/datamatrix/BC_EdifactEncoder.h"

#include <algorithm>

#include "fxbarcode/datamatrix/BC_Encoder.h"
#include "fxbarcode/datamatrix/BC_EncoderContext.h"
#include "fxbarcode/datamatrix/BC_HighLevelEncoder.h"
#include "fxbarcode/datamatrix/BC_SymbolInfo.h"

namespace {

WideString EncodeToEdifactCodewords(const WideString& sb) {
  size_t len = sb.GetLength();
  if (len == 0)
    return WideString();

  wchar_t c1 = sb[0];
  wchar_t c2 = len >= 2 ? sb[1] : 0;
  wchar_t c3 = len >= 3 ? sb[2] : 0;
  wchar_t c4 = len >= 4 ? sb[3] : 0;
  int32_t v = (c1 << 18) + (c2 << 12) + (c3 << 6) + c4;
  static constexpr size_t kBuflen = 3;
  wchar_t cw[kBuflen];
  cw[0] = static_cast<wchar_t>((v >> 16) & 255);
  cw[1] = static_cast<wchar_t>((v >> 8) & 255);
  cw[2] = static_cast<wchar_t>(v & 255);
  // TODO(tsepez): stop putting binary data in strings.
  return WideString(
      WideStringView(pdfium::make_span(cw).first(std::min(len, kBuflen))));
}

bool HandleEOD(CBC_EncoderContext* context, const WideString& buffer) {
  size_t count = buffer.GetLength();
  if (count == 0)
    return true;
  if (count > 4)
    return false;

  if (count == 1) {
    if (!context->UpdateSymbolInfo())
      return false;

    int32_t available =
        context->m_symbolInfo->data_capacity() - context->getCodewordCount();
    int32_t remaining = context->getRemainingCharacters();
    if (remaining == 0 && available <= 2)
      return true;
  }

  int32_t restChars = count - 1;
  WideString encoded = EncodeToEdifactCodewords(buffer);
  if (encoded.IsEmpty())
    return false;

  bool endOfSymbolReached = !context->hasMoreCharacters();
  bool restInAscii = endOfSymbolReached && restChars <= 2;
  if (restChars <= 2) {
    if (!context->UpdateSymbolInfo(context->getCodewordCount() + restChars))
      return false;

    int32_t available =
        context->m_symbolInfo->data_capacity() - context->getCodewordCount();
    if (available >= 3) {
      restInAscii = false;
      if (!context->UpdateSymbolInfo(context->getCodewordCount() +
                                     encoded.GetLength())) {
        return false;
      }
    }
  }

  if (restInAscii) {
    context->resetSymbolInfo();
    context->m_pos -= restChars;
  } else {
    context->writeCodewords(encoded);
  }
  context->SignalEncoderChange(CBC_HighLevelEncoder::Encoding::ASCII);
  return true;
}

bool AppendEncodedChar(wchar_t c, WideString* sb) {
  if (c >= ' ' && c <= '?') {
    *sb += c;
    return true;
  }

  if (c >= '@' && c <= '^') {
    *sb += (c - 64);
    return true;
  }

  return false;
}

}  // namespace

CBC_EdifactEncoder::CBC_EdifactEncoder() = default;

CBC_EdifactEncoder::~CBC_EdifactEncoder() = default;

CBC_HighLevelEncoder::Encoding CBC_EdifactEncoder::GetEncodingMode() {
  return CBC_HighLevelEncoder::Encoding::EDIFACT;
}

bool CBC_EdifactEncoder::Encode(CBC_EncoderContext* context) {
  WideString buffer;
  while (context->hasMoreCharacters()) {
    wchar_t c = context->getCurrentChar();
    if (!AppendEncodedChar(c, &buffer))
      return false;

    context->m_pos++;
    size_t count = buffer.GetLength();
    if (count >= 4) {
      WideString encoded = EncodeToEdifactCodewords(buffer);
      if (encoded.IsEmpty())
        return false;

      context->writeCodewords(encoded);
      buffer.Delete(0, 4);
      CBC_HighLevelEncoder::Encoding newMode =
          CBC_HighLevelEncoder::LookAheadTest(context->m_msg, context->m_pos,
                                              GetEncodingMode());
      if (newMode != GetEncodingMode()) {
        context->SignalEncoderChange(CBC_HighLevelEncoder::Encoding::ASCII);
        break;
      }
    }
  }
  buffer += static_cast<wchar_t>(31);
  return HandleEOD(context, buffer);
}
