// 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 2008 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 "fxbarcode/qrcode/BC_QRCoderMatrixUtil.h"

#include <iterator>

#include "fxbarcode/common/BC_CommonByteMatrix.h"
#include "fxbarcode/qrcode/BC_QRCoder.h"
#include "fxbarcode/qrcode/BC_QRCoderBitVector.h"
#include "fxbarcode/qrcode/BC_QRCoderErrorCorrectionLevel.h"
#include "fxbarcode/qrcode/BC_QRCoderMaskUtil.h"
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"

namespace {

constexpr uint8_t POSITION_DETECTION_PATTERN[7][7] = {
    {1, 1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 0, 0, 1}, {1, 0, 1, 1, 1, 0, 1},
    {1, 0, 1, 1, 1, 0, 1}, {1, 0, 1, 1, 1, 0, 1}, {1, 0, 0, 0, 0, 0, 1},
    {1, 1, 1, 1, 1, 1, 1}};

constexpr uint8_t POSITION_ADJUSTMENT_PATTERN[5][5] = {{1, 1, 1, 1, 1},
                                                       {1, 0, 0, 0, 1},
                                                       {1, 0, 1, 0, 1},
                                                       {1, 0, 0, 0, 1},
                                                       {1, 1, 1, 1, 1}};

constexpr size_t kNumCoordinate = 7;
constexpr uint8_t kPositionAdjustmentPatternCoordinates[39][kNumCoordinate] = {
    {6, 18, 0, 0, 0, 0, 0},         {6, 22, 0, 0, 0, 0, 0},
    {6, 26, 0, 0, 0, 0, 0},         {6, 30, 0, 0, 0, 0, 0},
    {6, 34, 0, 0, 0, 0, 0},         {6, 22, 38, 0, 0, 0, 0},
    {6, 24, 42, 0, 0, 0, 0},        {6, 26, 46, 0, 0, 0, 0},
    {6, 28, 50, 0, 0, 0, 0},        {6, 30, 54, 0, 0, 0, 0},
    {6, 32, 58, 0, 0, 0, 0},        {6, 34, 62, 0, 0, 0, 0},
    {6, 26, 46, 66, 0, 0, 0},       {6, 26, 48, 70, 0, 0, 0},
    {6, 26, 50, 74, 0, 0, 0},       {6, 30, 54, 78, 0, 0, 0},
    {6, 30, 56, 82, 0, 0, 0},       {6, 30, 58, 86, 0, 0, 0},
    {6, 34, 62, 90, 0, 0, 0},       {6, 28, 50, 72, 94, 0, 0},
    {6, 26, 50, 74, 98, 0, 0},      {6, 30, 54, 78, 102, 0, 0},
    {6, 28, 54, 80, 106, 0, 0},     {6, 32, 58, 84, 110, 0, 0},
    {6, 30, 58, 86, 114, 0, 0},     {6, 34, 62, 90, 118, 0, 0},
    {6, 26, 50, 74, 98, 122, 0},    {6, 30, 54, 78, 102, 126, 0},
    {6, 26, 52, 78, 104, 130, 0},   {6, 30, 56, 82, 108, 134, 0},
    {6, 34, 60, 86, 112, 138, 0},   {6, 30, 58, 86, 114, 142, 0},
    {6, 34, 62, 90, 118, 146, 0},   {6, 30, 54, 78, 102, 126, 150},
    {6, 24, 50, 76, 102, 128, 154}, {6, 28, 54, 80, 106, 132, 158},
    {6, 32, 58, 84, 110, 136, 162}, {6, 26, 54, 82, 110, 138, 166},
    {6, 30, 58, 86, 114, 142, 170},
};

const uint8_t TYPE_INFO_COORDINATES[15][2] = {
    {8, 0}, {8, 1}, {8, 2}, {8, 3}, {8, 4}, {8, 5}, {8, 7}, {8, 8},
    {7, 8}, {5, 8}, {4, 8}, {3, 8}, {2, 8}, {1, 8}, {0, 8},
};

const int32_t VERSION_INFO_POLY = 0x1f25;
const int32_t TYPE_INFO_POLY = 0x0537;
const int32_t TYPE_INFO_MASK_PATTERN = 0x5412;

bool IsEmpty(int32_t value) {
  return (uint8_t)value == 0xff;
}

bool IsValidValue(int32_t value) {
  return ((uint8_t)value == 0xff || (uint8_t)value == 0x00 ||
          (uint8_t)value == 0x01);
}

int32_t FindMSBSet(int32_t value) {
  int32_t numDigits = 0;
  while (value != 0) {
    value >>= 1;
    ++numDigits;
  }
  return numDigits;
}

bool EmbedDataBits(CBC_QRCoderBitVector* dataBits,
                   int32_t maskPattern,
                   CBC_CommonByteMatrix* matrix) {
  size_t szBitIndex = 0;
  int32_t direction = -1;
  int32_t x = matrix->GetWidth() - 1;
  int32_t y = matrix->GetHeight() - 1;
  while (x > 0) {
    if (x == 6)
      x -= 1;

    while (y >= 0 && y < static_cast<int32_t>(matrix->GetHeight())) {
      if (y == 6) {
        y += direction;
        continue;
      }
      for (int32_t i = 0; i < 2; i++) {
        int32_t xx = x - i;
        if (!IsEmpty(matrix->Get(xx, y))) {
          continue;
        }
        int32_t bit;
        if (szBitIndex < dataBits->Size()) {
          bit = dataBits->At(szBitIndex);
          szBitIndex++;
        } else {
          bit = 0;
        }
        DCHECK(CBC_QRCoder::IsValidMaskPattern(maskPattern));
        if (CBC_QRCoderMaskUtil::GetDataMaskBit(maskPattern, xx, y))
          bit ^= 0x01;
        matrix->Set(xx, y, bit);
      }
      y += direction;
    }
    direction = -direction;
    y += direction;
    x -= 2;
  }
  return szBitIndex == dataBits->Size();
}

int32_t CalculateBCHCode(int32_t value, int32_t poly) {
  int32_t msbSetInPoly = FindMSBSet(poly);
  value <<= msbSetInPoly - 1;
  while (FindMSBSet(value) >= msbSetInPoly) {
    value ^= poly << (FindMSBSet(value) - msbSetInPoly);
  }
  return value;
}

bool MakeTypeInfoBits(const CBC_QRCoderErrorCorrectionLevel* ecLevel,
                      int32_t maskPattern,
                      CBC_QRCoderBitVector* bits) {
  if (!CBC_QRCoder::IsValidMaskPattern(maskPattern))
    return false;

  int32_t typeInfo = (ecLevel->GetBits() << 3) | maskPattern;
  bits->AppendBits(typeInfo, 5);
  int32_t bchCode = CalculateBCHCode(typeInfo, TYPE_INFO_POLY);
  bits->AppendBits(bchCode, 10);
  CBC_QRCoderBitVector maskBits;
  maskBits.AppendBits(TYPE_INFO_MASK_PATTERN, 15);
  if (!bits->XOR(&maskBits))
    return false;

  DCHECK_EQ(bits->Size(), 15);
  return true;
}

void MakeVersionInfoBits(int32_t version, CBC_QRCoderBitVector* bits) {
  bits->AppendBits(version, 6);
  int32_t bchCode = CalculateBCHCode(version, VERSION_INFO_POLY);
  bits->AppendBits(bchCode, 12);
  DCHECK_EQ(bits->Size(), 18);
}

bool EmbedTypeInfo(const CBC_QRCoderErrorCorrectionLevel* ecLevel,
                   int32_t maskPattern,
                   CBC_CommonByteMatrix* matrix) {
  CBC_QRCoderBitVector typeInfoBits;
  if (!MakeTypeInfoBits(ecLevel, maskPattern, &typeInfoBits))
    return false;

  for (size_t i = 0; i < typeInfoBits.Size(); i++) {
    int32_t bit = typeInfoBits.At(typeInfoBits.Size() - 1 - i);
    int32_t x1 = TYPE_INFO_COORDINATES[i][0];
    int32_t y1 = TYPE_INFO_COORDINATES[i][1];
    matrix->Set(x1, y1, bit);
    if (i < 8) {
      int32_t x2 = matrix->GetWidth() - i - 1;
      int32_t y2 = 8;
      matrix->Set(x2, y2, bit);
    } else {
      int32_t x2 = 8;
      int32_t y2 = matrix->GetHeight() - 7 + (i - 8);
      matrix->Set(x2, y2, bit);
    }
  }
  return true;
}

void MaybeEmbedVersionInfo(int32_t version, CBC_CommonByteMatrix* matrix) {
  if (version < 7)
    return;

  CBC_QRCoderBitVector versionInfoBits;
  MakeVersionInfoBits(version, &versionInfoBits);
  int32_t bitIndex = 6 * 3 - 1;
  for (int32_t i = 0; i < 6; i++) {
    for (int32_t j = 0; j < 3; j++) {
      int32_t bit = versionInfoBits.At(bitIndex);
      bitIndex--;
      matrix->Set(i, matrix->GetHeight() - 11 + j, bit);
      matrix->Set(matrix->GetHeight() - 11 + j, i, bit);
    }
  }
}

bool EmbedTimingPatterns(CBC_CommonByteMatrix* matrix) {
  for (size_t i = 8; i + 8 < matrix->GetWidth(); i++) {
    const uint8_t bit = static_cast<uint8_t>((i + 1) % 2);
    if (!IsValidValue(matrix->Get(i, 6)))
      return false;

    if (IsEmpty(matrix->Get(i, 6)))
      matrix->Set(i, 6, bit);

    if (!IsValidValue(matrix->Get(6, i)))
      return false;

    if (IsEmpty(matrix->Get(6, i)))
      matrix->Set(6, i, bit);
  }
  return true;
}

bool EmbedDarkDotAtLeftBottomCorner(CBC_CommonByteMatrix* matrix) {
  if (matrix->Get(8, matrix->GetHeight() - 8) == 0)
    return false;

  matrix->Set(8, matrix->GetHeight() - 8, 1);
  return true;
}

bool EmbedHorizontalSeparationPattern(int32_t xStart,
                                      int32_t yStart,
                                      CBC_CommonByteMatrix* matrix) {
  for (int32_t x = 0; x < 8; x++) {
    if (!IsEmpty(matrix->Get(xStart + x, yStart)))
      return false;

    matrix->Set(xStart + x, yStart, 0);
  }
  return true;
}

bool EmbedVerticalSeparationPattern(int32_t xStart,
                                    int32_t yStart,
                                    CBC_CommonByteMatrix* matrix) {
  for (int32_t y = 0; y < 7; y++) {
    if (!IsEmpty(matrix->Get(xStart, yStart + y)))
      return false;

    matrix->Set(xStart, yStart + y, 0);
  }
  return true;
}

bool EmbedPositionAdjustmentPattern(int32_t xStart,
                                    int32_t yStart,
                                    CBC_CommonByteMatrix* matrix) {
  for (int32_t y = 0; y < 5; y++) {
    for (int32_t x = 0; x < 5; x++) {
      if (!IsEmpty(matrix->Get(xStart + x, y + yStart)))
        return false;

      matrix->Set(xStart + x, yStart + y, POSITION_ADJUSTMENT_PATTERN[y][x]);
    }
  }
  return true;
}

bool EmbedPositionDetectionPattern(int32_t xStart,
                                   int32_t yStart,
                                   CBC_CommonByteMatrix* matrix) {
  for (int32_t y = 0; y < 7; y++) {
    for (int32_t x = 0; x < 7; x++) {
      if (!IsEmpty(matrix->Get(xStart + x, yStart + y)))
        return false;

      matrix->Set(xStart + x, yStart + y, POSITION_DETECTION_PATTERN[y][x]);
    }
  }
  return true;
}

bool EmbedPositionDetectionPatternsAndSeparators(CBC_CommonByteMatrix* matrix) {
  constexpr int32_t pdpWidth = 7;
  if (!EmbedPositionDetectionPattern(0, 0, matrix))
    return false;
  if (!EmbedPositionDetectionPattern(matrix->GetWidth() - pdpWidth, 0, matrix))
    return false;
  if (!EmbedPositionDetectionPattern(0, matrix->GetWidth() - pdpWidth, matrix))
    return false;

  constexpr int32_t hspWidth = 8;
  if (!EmbedHorizontalSeparationPattern(0, hspWidth - 1, matrix))
    return false;
  if (!EmbedHorizontalSeparationPattern(matrix->GetWidth() - hspWidth,
                                        hspWidth - 1, matrix)) {
    return false;
  }
  if (!EmbedHorizontalSeparationPattern(0, matrix->GetWidth() - hspWidth,
                                        matrix)) {
    return false;
  }

  constexpr int32_t vspSize = 7;
  if (!EmbedVerticalSeparationPattern(vspSize, 0, matrix))
    return false;
  if (!EmbedVerticalSeparationPattern(matrix->GetHeight() - vspSize - 1, 0,
                                      matrix)) {
    return false;
  }
  if (!EmbedVerticalSeparationPattern(vspSize, matrix->GetHeight() - vspSize,
                                      matrix)) {
    return false;
  }
  return true;
}

bool MaybeEmbedPositionAdjustmentPatterns(int32_t version,
                                          CBC_CommonByteMatrix* matrix) {
  if (version < 2)
    return true;

  const size_t index = version - 2;
  if (index >= std::size(kPositionAdjustmentPatternCoordinates))
    return false;

  const auto* coordinates = &kPositionAdjustmentPatternCoordinates[index][0];
  for (size_t i = 0; i < kNumCoordinate; i++) {
    const int32_t y = coordinates[i];
    if (y == 0)
      break;
    for (size_t j = 0; j < kNumCoordinate; j++) {
      const int32_t x = coordinates[j];
      if (x == 0)
        break;

      if (IsEmpty(matrix->Get(x, y))) {
        if (!EmbedPositionAdjustmentPattern(x - 2, y - 2, matrix))
          return false;
      }
    }
  }
  return true;
}

bool EmbedBasicPatterns(int32_t version, CBC_CommonByteMatrix* matrix) {
  if (!EmbedPositionDetectionPatternsAndSeparators(matrix))
    return false;
  if (!EmbedDarkDotAtLeftBottomCorner(matrix))
    return false;
  if (!MaybeEmbedPositionAdjustmentPatterns(version, matrix))
    return false;
  if (!EmbedTimingPatterns(matrix))
    return false;
  return true;
}

}  // namespace

bool CBC_QRCoderMatrixUtil::BuildMatrix(
    CBC_QRCoderBitVector* dataBits,
    const CBC_QRCoderErrorCorrectionLevel* ecLevel,
    int32_t version,
    int32_t maskPattern,
    CBC_CommonByteMatrix* matrix) {
  if (!dataBits || !matrix)
    return false;

  matrix->Fill(0xff);

  if (!EmbedBasicPatterns(version, matrix))
    return false;
  if (!EmbedTypeInfo(ecLevel, maskPattern, matrix))
    return false;

  MaybeEmbedVersionInfo(version, matrix);
  return EmbedDataBits(dataBits, maskPattern, matrix);
}
