// 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
// 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/common/BC_CommonBitMatrix.h"
#include "fxbarcode/datamatrix/BC_Encoder.h"
#include "fxbarcode/datamatrix/BC_EncoderContext.h"
#include "fxbarcode/datamatrix/BC_HighLevelEncoder.h"
#include "fxbarcode/datamatrix/BC_SymbolInfo.h"
#include "fxbarcode/utils.h"

namespace {

CFX_WideString EncodeToCodewords(const CFX_WideString& sb, int32_t startPos) {
  int32_t len = sb.GetLength() - startPos;
  if (len == 0)
    return CFX_WideString();

  wchar_t c1 = sb.GetAt(startPos);
  wchar_t c2 = len >= 2 ? sb.GetAt(startPos + 1) : 0;
  wchar_t c3 = len >= 3 ? sb.GetAt(startPos + 2) : 0;
  wchar_t c4 = len >= 4 ? sb.GetAt(startPos + 3) : 0;
  int32_t v = (c1 << 18) + (c2 << 12) + (c3 << 6) + c4;
  constexpr int32_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);
  return CFX_WideString(cw, std::min(len, kBuflen));
}

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

  if (count == 1) {
    int32_t e = BCExceptionNO;
    context->updateSymbolInfo(e);
    if (e != BCExceptionNO)
      return false;

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

  int32_t restChars = count - 1;
  CFX_WideString encoded = EncodeToCodewords(buffer, 0);
  if (encoded.IsEmpty())
    return false;

  bool endOfSymbolReached = !context->hasMoreCharacters();
  bool restInAscii = endOfSymbolReached && restChars <= 2;
  if (restChars <= 2) {
    int32_t e = BCExceptionNO;
    context->updateSymbolInfo(context->getCodewordCount() + restChars, e);
    if (e != BCExceptionNO)
      return false;

    int32_t available =
        context->m_symbolInfo->dataCapacity() - context->getCodewordCount();
    if (available >= 3) {
      restInAscii = false;
      context->updateSymbolInfo(
          context->getCodewordCount() + encoded.GetLength(), e);
      if (e != BCExceptionNO)
        return false;
    }
  }

  if (restInAscii) {
    context->resetSymbolInfo();
    context->m_pos -= restChars;
  } else {
    context->writeCodewords(encoded);
  }
  context->signalEncoderChange(ASCII_ENCODATION);
  return true;
}

void encodeChar(wchar_t c, CFX_WideString* sb, int32_t& e) {
  if (c >= ' ' && c <= '?') {
    *sb += c;
  } else if (c >= '@' && c <= '^') {
    *sb += (wchar_t)(c - 64);
  } else {
    e = BCExceptionIllegalArgument;
  }
}

}  // namespace

CBC_EdifactEncoder::CBC_EdifactEncoder() {}

CBC_EdifactEncoder::~CBC_EdifactEncoder() {}

int32_t CBC_EdifactEncoder::getEncodingMode() {
  return EDIFACT_ENCODATION;
}

void CBC_EdifactEncoder::Encode(CBC_EncoderContext& context, int32_t& e) {
  CFX_WideString buffer;
  while (context.hasMoreCharacters()) {
    wchar_t c = context.getCurrentChar();
    encodeChar(c, &buffer, e);
    if (e != BCExceptionNO) {
      return;
    }
    context.m_pos++;
    int32_t count = buffer.GetLength();
    if (count >= 4) {
      CFX_WideString encoded = EncodeToCodewords(buffer, 0);
      if (encoded.IsEmpty()) {
        e = BCExceptionGeneric;
        return;
      }
      context.writeCodewords(encoded);
      buffer.Delete(0, 4);
      int32_t newMode = CBC_HighLevelEncoder::lookAheadTest(
          context.m_msg, context.m_pos, getEncodingMode());
      if (newMode != getEncodingMode()) {
        context.signalEncoderChange(ASCII_ENCODATION);
        break;
      }
    }
  }
  buffer += static_cast<wchar_t>(31);
  if (!HandleEOD(&context, buffer))
    e = BCExceptionGeneric;
}
