// 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 2007 ZXing authors
 *
 * 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 "xfa/fxbarcode/qrcode/BC_QRBitMatrixParser.h"

#include <memory>

#include "xfa/fxbarcode/common/BC_CommonBitMatrix.h"
#include "xfa/fxbarcode/qrcode/BC_QRCoderFormatInformation.h"
#include "xfa/fxbarcode/qrcode/BC_QRCoderVersion.h"
#include "xfa/fxbarcode/qrcode/BC_QRDataMask.h"
#include "xfa/fxbarcode/utils.h"

CBC_QRBitMatrixParser::CBC_QRBitMatrixParser() {}
void CBC_QRBitMatrixParser::Init(CBC_CommonBitMatrix* bitMatrix, int32_t& e) {
  m_dimension = bitMatrix->GetDimension(e);
  BC_EXCEPTION_CHECK_ReturnVoid(e);
  m_tempBitMatrix = bitMatrix;
  if (m_dimension < 21 || (m_dimension & 0x03) != 1) {
    e = BCExceptionRead;
    BC_EXCEPTION_CHECK_ReturnVoid(e);
  }
  m_bitMatrix = m_tempBitMatrix;
  m_parsedFormatInfo = NULL;
  m_version = NULL;
}
CBC_QRBitMatrixParser::~CBC_QRBitMatrixParser() {
  delete m_parsedFormatInfo;
}
CBC_QRCoderFormatInformation* CBC_QRBitMatrixParser::ReadFormatInformation(
    int32_t& e) {
  if (m_parsedFormatInfo) {
    return m_parsedFormatInfo;
  }
  int32_t formatInfoBits = 0;
  int32_t j;
  for (j = 0; j < 6; j++) {
    formatInfoBits = CopyBit(8, j, formatInfoBits);
  }
  formatInfoBits = CopyBit(8, 7, formatInfoBits);
  formatInfoBits = CopyBit(8, 8, formatInfoBits);
  formatInfoBits = CopyBit(7, 8, formatInfoBits);
  for (int32_t i = 5; i >= 0; i--) {
    formatInfoBits = CopyBit(i, 8, formatInfoBits);
  }
  m_parsedFormatInfo =
      CBC_QRCoderFormatInformation::DecodeFormatInformation(formatInfoBits);
  if (m_parsedFormatInfo) {
    return m_parsedFormatInfo;
  }
  int32_t dimension = m_bitMatrix->GetDimension(e);
  BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
  formatInfoBits = 0;
  int32_t iMin = dimension - 8;
  for (j = dimension - 1; j >= iMin; j--) {
    formatInfoBits = CopyBit(j, 8, formatInfoBits);
  }
  for (int32_t k = dimension - 7; k < dimension; k++) {
    formatInfoBits = CopyBit(8, k, formatInfoBits);
  }
  m_parsedFormatInfo =
      CBC_QRCoderFormatInformation::DecodeFormatInformation(formatInfoBits);
  if (m_parsedFormatInfo) {
    return m_parsedFormatInfo;
  }
  e = BCExceptionRead;
  BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
  return NULL;
}
CBC_QRCoderVersion* CBC_QRBitMatrixParser::ReadVersion(int32_t& e) {
  if (m_version) {
    return m_version;
  }
  int32_t dimension = m_bitMatrix->GetDimension(e);
  BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
  int32_t provisionVersion = (dimension - 17) >> 2;
  if (provisionVersion <= 6) {
    CBC_QRCoderVersion* qrv =
        CBC_QRCoderVersion::GetVersionForNumber(provisionVersion, e);
    BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
    return qrv;
  }
  int32_t versionBits = 0;
  for (int32_t i = 5; i >= 0; i--) {
    int32_t jMin = dimension - 11;
    for (int32_t j = dimension - 9; j >= jMin; j--) {
      versionBits = CopyBit(i, j, versionBits);
    }
  }
  m_version = CBC_QRCoderVersion::DecodeVersionInformation(versionBits, e);
  BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
  if (m_version && m_version->GetDimensionForVersion() == dimension) {
    return m_version;
  }
  versionBits = 0;
  for (int32_t j = 5; j >= 0; j--) {
    int32_t iMin = dimension - 11;
    for (int32_t i = dimension - 9; i >= iMin; i--) {
      versionBits = CopyBit(i, j, versionBits);
    }
  }
  m_version = CBC_QRCoderVersion::DecodeVersionInformation(versionBits, e);
  BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
  if (m_version && m_version->GetDimensionForVersion() == dimension) {
    return m_version;
  }
  e = BCExceptionRead;
  BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
  return NULL;
}
int32_t CBC_QRBitMatrixParser::CopyBit(int32_t i,
                                       int32_t j,
                                       int32_t versionBits) {
  return m_bitMatrix->Get(j, i) ? (versionBits << 1) | 0x1 : versionBits << 1;
}
CFX_ByteArray* CBC_QRBitMatrixParser::ReadCodewords(int32_t& e) {
  CBC_QRCoderFormatInformation* formatInfo = ReadFormatInformation(e);
  BC_EXCEPTION_CHECK_ReturnValue(e, NULL) CBC_QRCoderVersion* version =
      ReadVersion(e);
  BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
  CBC_QRDataMask* dataMask =
      CBC_QRDataMask::ForReference((int32_t)(formatInfo->GetDataMask()), e);
  BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
  int32_t dimension = m_bitMatrix->GetDimension(e);
  BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
  dataMask->UnmaskBitMatrix(m_bitMatrix, dimension);
  std::unique_ptr<CBC_CommonBitMatrix> functionPattern(
      version->BuildFunctionPattern(e));
  BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
  FX_BOOL readingUp = TRUE;
  std::unique_ptr<CFX_ByteArray> result(new CFX_ByteArray);
  result->SetSize(version->GetTotalCodeWords());
  int32_t resultOffset = 0;
  int32_t currentByte = 0;
  int32_t bitsRead = 0;
  for (int32_t j = dimension - 1; j > 0; j -= 2) {
    if (j == 6) {
      j--;
    }
    for (int32_t count = 0; count < dimension; count++) {
      int32_t i = readingUp ? dimension - 1 - count : count;
      for (int32_t col = 0; col < 2; col++) {
        if (!functionPattern->Get(j - col, i)) {
          bitsRead++;
          currentByte <<= 1;
          if (m_bitMatrix->Get(j - col, i)) {
            currentByte |= 1;
          }
          if (bitsRead == 8) {
            (*result)[resultOffset++] = (uint8_t)currentByte;
            bitsRead = 0;
            currentByte = 0;
          }
        }
      }
    }
    readingUp ^= TRUE;
  }
  if (resultOffset != version->GetTotalCodeWords()) {
    e = BCExceptionRead;
    BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
  }
  return result.release();
}
