// go-qrcode
// Copyright 2014 Tom Harwood

package qrcode

import (
	"log"

	bitset "github.com/skip2/go-qrcode/bitset"
)

// Error detection/recovery capacity.
//
// There are several levels of error detection/recovery capacity. Higher levels
// of error recovery are able to correct more errors, with the trade-off of
// increased symbol size.
type RecoveryLevel int

const (
	// Level L: 7% error recovery.
	Low RecoveryLevel = iota

	// Level M: 15% error recovery. Good default choice.
	Medium

	// Level Q: 25% error recovery.
	High

	// Level H: 30% error recovery.
	Highest
)

// qrCodeVersion describes the data length and encoding order of a single QR
// Code version. There are 40 versions numbers x 4 recovery levels == 160
// possible qrCodeVersion structures.
type qrCodeVersion struct {
	// Version number (1-40 inclusive).
	version int

	// Error recovery level.
	level RecoveryLevel

	dataEncoderType dataEncoderType

	// Encoded data can be split into multiple blocks. Each block contains data
	// and error recovery bytes.
	//
	// Larger QR Codes contain more blocks.
	block []block

	// Number of bits required to pad the combined data & error correction bit
	// stream up to the symbol's full capacity.
	numRemainderBits int
}

type block struct {
	numBlocks int

	// Total codewords (numCodewords == numErrorCodewords+numDataCodewords).
	numCodewords int

	// Number of data codewords.
	numDataCodewords int
}

var (
	versions = []qrCodeVersion{
		{
			1,
			Low,
			dataEncoderType1To9,
			[]block{
				{
					1,
					26,
					19,
				},
			},
			0,
		},
		{
			1,
			Medium,
			dataEncoderType1To9,
			[]block{
				{
					1,
					26,
					16,
				},
			},
			0,
		},
		{
			1,
			High,
			dataEncoderType1To9,
			[]block{
				{
					1,
					26,
					13,
				},
			},
			0,
		},
		{
			1,
			Highest,
			dataEncoderType1To9,
			[]block{
				{
					1,
					26,
					9,
				},
			},
			0,
		},
		{
			2,
			Low,
			dataEncoderType1To9,
			[]block{
				{
					1,
					44,
					34,
				},
			},
			7,
		},
		{
			2,
			Medium,
			dataEncoderType1To9,
			[]block{
				{
					1,
					44,
					28,
				},
			},
			7,
		},
		{
			2,
			High,
			dataEncoderType1To9,
			[]block{
				{
					1,
					44,
					22,
				},
			},
			7,
		},
		{
			2,
			Highest,
			dataEncoderType1To9,
			[]block{
				{
					1,
					44,
					16,
				},
			},
			7,
		},
		{
			3,
			Low,
			dataEncoderType1To9,
			[]block{
				{
					1,
					70,
					55,
				},
			},
			7,
		},
		{
			3,
			Medium,
			dataEncoderType1To9,
			[]block{
				{
					1,
					70,
					44,
				},
			},
			7,
		},
		{
			3,
			High,
			dataEncoderType1To9,
			[]block{
				{
					2,
					35,
					17,
				},
			},
			7,
		},
		{
			3,
			Highest,
			dataEncoderType1To9,
			[]block{
				{
					2,
					35,
					13,
				},
			},
			7,
		},
		{
			4,
			Low,
			dataEncoderType1To9,
			[]block{
				{
					1,
					100,
					80,
				},
			},
			7,
		},
		{
			4,
			Medium,
			dataEncoderType1To9,
			[]block{
				{
					2,
					50,
					32,
				},
			},
			7,
		},
		{
			4,
			High,
			dataEncoderType1To9,
			[]block{
				{
					2,
					50,
					24,
				},
			},
			7,
		},
		{
			4,
			Highest,
			dataEncoderType1To9,
			[]block{
				{
					4,
					25,
					9,
				},
			},
			7,
		},
		{
			5,
			Low,
			dataEncoderType1To9,
			[]block{
				{
					1,
					134,
					108,
				},
			},
			7,
		},
		{
			5,
			Medium,
			dataEncoderType1To9,
			[]block{
				{
					2,
					67,
					43,
				},
			},
			7,
		},
		{
			5,
			High,
			dataEncoderType1To9,
			[]block{
				{
					2,
					33,
					15,
				},
				{
					2,
					34,
					16,
				},
			},
			7,
		},
		{
			5,
			Highest,
			dataEncoderType1To9,
			[]block{
				{
					2,
					33,
					11,
				},
				{
					2,
					34,
					12,
				},
			},
			7,
		},
		{
			6,
			Low,
			dataEncoderType1To9,
			[]block{
				{
					2,
					86,
					68,
				},
			},
			7,
		},
		{
			6,
			Medium,
			dataEncoderType1To9,
			[]block{
				{
					4,
					43,
					27,
				},
			},
			7,
		},
		{
			6,
			High,
			dataEncoderType1To9,
			[]block{
				{
					4,
					43,
					19,
				},
			},
			7,
		},
		{
			6,
			Highest,
			dataEncoderType1To9,
			[]block{
				{
					4,
					43,
					15,
				},
			},
			7,
		},
		{
			7,
			Low,
			dataEncoderType1To9,
			[]block{
				{
					2,
					98,
					78,
				},
			},
			0,
		},
		{
			7,
			Medium,
			dataEncoderType1To9,
			[]block{
				{
					4,
					49,
					31,
				},
			},
			0,
		},
		{
			7,
			High,
			dataEncoderType1To9,
			[]block{
				{
					2,
					32,
					14,
				},
				{
					4,
					33,
					15,
				},
			},
			0,
		},
		{
			7,
			Highest,
			dataEncoderType1To9,
			[]block{
				{
					4,
					39,
					13,
				},
				{
					1,
					40,
					14,
				},
			},
			0,
		},
		{
			8,
			Low,
			dataEncoderType1To9,
			[]block{
				{
					2,
					121,
					97,
				},
			},
			0,
		},
		{
			8,
			Medium,
			dataEncoderType1To9,
			[]block{
				{
					2,
					60,
					38,
				},
				{
					2,
					61,
					39,
				},
			},
			0,
		},
		{
			8,
			High,
			dataEncoderType1To9,
			[]block{
				{
					4,
					40,
					18,
				},
				{
					2,
					41,
					19,
				},
			},
			0,
		},
		{
			8,
			Highest,
			dataEncoderType1To9,
			[]block{
				{
					4,
					40,
					14,
				},
				{
					2,
					41,
					15,
				},
			},
			0,
		},
		{
			9,
			Low,
			dataEncoderType1To9,
			[]block{
				{
					2,
					146,
					116,
				},
			},
			0,
		},
		{
			9,
			Medium,
			dataEncoderType1To9,
			[]block{
				{
					3,
					58,
					36,
				},
				{
					2,
					59,
					37,
				},
			},
			0,
		},
		{
			9,
			High,
			dataEncoderType1To9,
			[]block{
				{
					4,
					36,
					16,
				},
				{
					4,
					37,
					17,
				},
			},
			0,
		},
		{
			9,
			Highest,
			dataEncoderType1To9,
			[]block{
				{
					4,
					36,
					12,
				},
				{
					4,
					37,
					13,
				},
			},
			0,
		},
		{
			10,
			Low,
			dataEncoderType10To26,
			[]block{
				{
					2,
					86,
					68,
				},
				{
					2,
					87,
					69,
				},
			},
			0,
		},
		{
			10,
			Medium,
			dataEncoderType10To26,
			[]block{
				{
					4,
					69,
					43,
				},
				{
					1,
					70,
					44,
				},
			},
			0,
		},
		{
			10,
			High,
			dataEncoderType10To26,
			[]block{
				{
					6,
					43,
					19,
				},
				{
					2,
					44,
					20,
				},
			},
			0,
		},
		{
			10,
			Highest,
			dataEncoderType10To26,
			[]block{
				{
					6,
					43,
					15,
				},
				{
					2,
					44,
					16,
				},
			},
			0,
		},
		{
			11,
			Low,
			dataEncoderType10To26,
			[]block{
				{
					4,
					101,
					81,
				},
			},
			0,
		},
		{
			11,
			Medium,
			dataEncoderType10To26,
			[]block{
				{
					1,
					80,
					50,
				},
				{
					4,
					81,
					51,
				},
			},
			0,
		},
		{
			11,
			High,
			dataEncoderType10To26,
			[]block{
				{
					4,
					50,
					22,
				},
				{
					4,
					51,
					23,
				},
			},
			0,
		},
		{
			11,
			Highest,
			dataEncoderType10To26,
			[]block{
				{
					3,
					36,
					12,
				},
				{
					8,
					37,
					13,
				},
			},
			0,
		},
		{
			12,
			Low,
			dataEncoderType10To26,
			[]block{
				{
					2,
					116,
					92,
				},
				{
					2,
					117,
					93,
				},
			},
			0,
		},
		{
			12,
			Medium,
			dataEncoderType10To26,
			[]block{
				{
					6,
					58,
					36,
				},
				{
					2,
					59,
					37,
				},
			},
			0,
		},
		{
			12,
			High,
			dataEncoderType10To26,
			[]block{
				{
					4,
					46,
					20,
				},
				{
					6,
					47,
					21,
				},
			},
			0,
		},
		{
			12,
			Highest,
			dataEncoderType10To26,
			[]block{
				{
					7,
					42,
					14,
				},
				{
					4,
					43,
					15,
				},
			},
			0,
		},
		{
			13,
			Low,
			dataEncoderType10To26,
			[]block{
				{
					4,
					133,
					107,
				},
			},
			0,
		},
		{
			13,
			Medium,
			dataEncoderType10To26,
			[]block{
				{
					8,
					59,
					37,
				},
				{
					1,
					60,
					38,
				},
			},
			0,
		},
		{
			13,
			High,
			dataEncoderType10To26,
			[]block{
				{
					8,
					44,
					20,
				},
				{
					4,
					45,
					21,
				},
			},
			0,
		},
		{
			13,
			Highest,
			dataEncoderType10To26,
			[]block{
				{
					12,
					33,
					11,
				},
				{
					4,
					34,
					12,
				},
			},
			0,
		},
		{
			14,
			Low,
			dataEncoderType10To26,
			[]block{
				{
					3,
					145,
					115,
				},
				{
					1,
					146,
					116,
				},
			},
			3,
		},
		{
			14,
			Medium,
			dataEncoderType10To26,
			[]block{
				{
					4,
					64,
					40,
				},
				{
					5,
					65,
					41,
				},
			},
			3,
		},
		{
			14,
			High,
			dataEncoderType10To26,
			[]block{
				{
					11,
					36,
					16,
				},
				{
					5,
					37,
					17,
				},
			},
			3,
		},
		{
			14,
			Highest,
			dataEncoderType10To26,
			[]block{
				{
					11,
					36,
					12,
				},
				{
					5,
					37,
					13,
				},
			},
			3,
		},
		{
			15,
			Low,
			dataEncoderType10To26,
			[]block{
				{
					5,
					109,
					87,
				},
				{
					1,
					110,
					88,
				},
			},
			3,
		},
		{
			15,
			Medium,
			dataEncoderType10To26,
			[]block{
				{
					5,
					65,
					41,
				},
				{
					5,
					66,
					42,
				},
			},
			3,
		},
		{
			15,
			High,
			dataEncoderType10To26,
			[]block{
				{
					5,
					54,
					24,
				},
				{
					7,
					55,
					25,
				},
			},
			3,
		},
		{
			15,
			Highest,
			dataEncoderType10To26,
			[]block{
				{
					11,
					36,
					12,
				},
				{
					7,
					37,
					13,
				},
			},
			3,
		},
		{
			16,
			Low,
			dataEncoderType10To26,
			[]block{
				{
					5,
					122,
					98,
				},
				{
					1,
					123,
					99,
				},
			},
			3,
		},
		{
			16,
			Medium,
			dataEncoderType10To26,
			[]block{
				{
					7,
					73,
					45,
				},
				{
					3,
					74,
					46,
				},
			},
			3,
		},
		{
			16,
			High,
			dataEncoderType10To26,
			[]block{
				{
					15,
					43,
					19,
				},
				{
					2,
					44,
					20,
				},
			},
			3,
		},
		{
			16,
			Highest,
			dataEncoderType10To26,
			[]block{
				{
					3,
					45,
					15,
				},
				{
					13,
					46,
					16,
				},
			},
			3,
		},
		{
			17,
			Low,
			dataEncoderType10To26,
			[]block{
				{
					1,
					135,
					107,
				},
				{
					5,
					136,
					108,
				},
			},
			3,
		},
		{
			17,
			Medium,
			dataEncoderType10To26,
			[]block{
				{
					10,
					74,
					46,
				},
				{
					1,
					75,
					47,
				},
			},
			3,
		},
		{
			17,
			High,
			dataEncoderType10To26,
			[]block{
				{
					1,
					50,
					22,
				},
				{
					15,
					51,
					23,
				},
			},
			3,
		},
		{
			17,
			Highest,
			dataEncoderType10To26,
			[]block{
				{
					2,
					42,
					14,
				},
				{
					17,
					43,
					15,
				},
			},
			3,
		},
		{
			18,
			Low,
			dataEncoderType10To26,
			[]block{
				{
					5,
					150,
					120,
				},
				{
					1,
					151,
					121,
				},
			},
			3,
		},
		{
			18,
			Medium,
			dataEncoderType10To26,
			[]block{
				{
					9,
					69,
					43,
				},
				{
					4,
					70,
					44,
				},
			},
			3,
		},
		{
			18,
			High,
			dataEncoderType10To26,
			[]block{
				{
					17,
					50,
					22,
				},
				{
					1,
					51,
					23,
				},
			},
			3,
		},
		{
			18,
			Highest,
			dataEncoderType10To26,
			[]block{
				{
					2,
					42,
					14,
				},
				{
					19,
					43,
					15,
				},
			},
			3,
		},
		{
			19,
			Low,
			dataEncoderType10To26,
			[]block{
				{
					3,
					141,
					113,
				},
				{
					4,
					142,
					114,
				},
			},
			3,
		},
		{
			19,
			Medium,
			dataEncoderType10To26,
			[]block{
				{
					3,
					70,
					44,
				},
				{
					11,
					71,
					45,
				},
			},
			3,
		},
		{
			19,
			High,
			dataEncoderType10To26,
			[]block{
				{
					17,
					47,
					21,
				},
				{
					4,
					48,
					22,
				},
			},
			3,
		},
		{
			19,
			Highest,
			dataEncoderType10To26,
			[]block{
				{
					9,
					39,
					13,
				},
				{
					16,
					40,
					14,
				},
			},
			3,
		},
		{
			20,
			Low,
			dataEncoderType10To26,
			[]block{
				{
					3,
					135,
					107,
				},
				{
					5,
					136,
					108,
				},
			},
			3,
		},
		{
			20,
			Medium,
			dataEncoderType10To26,
			[]block{
				{
					3,
					67,
					41,
				},
				{
					13,
					68,
					42,
				},
			},
			3,
		},
		{
			20,
			High,
			dataEncoderType10To26,
			[]block{
				{
					15,
					54,
					24,
				},
				{
					5,
					55,
					25,
				},
			},
			3,
		},
		{
			20,
			Highest,
			dataEncoderType10To26,
			[]block{
				{
					15,
					43,
					15,
				},
				{
					10,
					44,
					16,
				},
			},
			3,
		},
		{
			21,
			Low,
			dataEncoderType10To26,
			[]block{
				{
					4,
					144,
					116,
				},
				{
					4,
					145,
					117,
				},
			},
			4,
		},
		{
			21,
			Medium,
			dataEncoderType10To26,
			[]block{
				{
					17,
					68,
					42,
				},
			},
			4,
		},
		{
			21,
			High,
			dataEncoderType10To26,
			[]block{
				{
					17,
					50,
					22,
				},
				{
					6,
					51,
					23,
				},
			},
			4,
		},
		{
			21,
			Highest,
			dataEncoderType10To26,
			[]block{
				{
					19,
					46,
					16,
				},
				{
					6,
					47,
					17,
				},
			},
			4,
		},
		{
			22,
			Low,
			dataEncoderType10To26,
			[]block{
				{
					2,
					139,
					111,
				},
				{
					7,
					140,
					112,
				},
			},
			4,
		},
		{
			22,
			Medium,
			dataEncoderType10To26,
			[]block{
				{
					17,
					74,
					46,
				},
			},
			4,
		},
		{
			22,
			High,
			dataEncoderType10To26,
			[]block{
				{
					7,
					54,
					24,
				},
				{
					16,
					55,
					25,
				},
			},
			4,
		},
		{
			22,
			Highest,
			dataEncoderType10To26,
			[]block{
				{
					34,
					37,
					13,
				},
			},
			4,
		},
		{
			23,
			Low,
			dataEncoderType10To26,
			[]block{
				{
					4,
					151,
					121,
				},
				{
					5,
					152,
					122,
				},
			},
			4,
		},
		{
			23,
			Medium,
			dataEncoderType10To26,
			[]block{
				{
					4,
					75,
					47,
				},
				{
					14,
					76,
					48,
				},
			},
			4,
		},
		{
			23,
			High,
			dataEncoderType10To26,
			[]block{
				{
					11,
					54,
					24,
				},
				{
					14,
					55,
					25,
				},
			},
			4,
		},
		{
			23,
			Highest,
			dataEncoderType10To26,
			[]block{
				{
					16,
					45,
					15,
				},
				{
					14,
					46,
					16,
				},
			},
			4,
		},
		{
			24,
			Low,
			dataEncoderType10To26,
			[]block{
				{
					6,
					147,
					117,
				},
				{
					4,
					148,
					118,
				},
			},
			4,
		},
		{
			24,
			Medium,
			dataEncoderType10To26,
			[]block{
				{
					6,
					73,
					45,
				},
				{
					14,
					74,
					46,
				},
			},
			4,
		},
		{
			24,
			High,
			dataEncoderType10To26,
			[]block{
				{
					11,
					54,
					24,
				},
				{
					16,
					55,
					25,
				},
			},
			4,
		},
		{
			24,
			Highest,
			dataEncoderType10To26,
			[]block{
				{
					30,
					46,
					16,
				},
				{
					2,
					47,
					17,
				},
			},
			4,
		},
		{
			25,
			Low,
			dataEncoderType10To26,
			[]block{
				{
					8,
					132,
					106,
				},
				{
					4,
					133,
					107,
				},
			},
			4,
		},
		{
			25,
			Medium,
			dataEncoderType10To26,
			[]block{
				{
					8,
					75,
					47,
				},
				{
					13,
					76,
					48,
				},
			},
			4,
		},
		{
			25,
			High,
			dataEncoderType10To26,
			[]block{
				{
					7,
					54,
					24,
				},
				{
					22,
					55,
					25,
				},
			},
			4,
		},
		{
			25,
			Highest,
			dataEncoderType10To26,
			[]block{
				{
					22,
					45,
					15,
				},
				{
					13,
					46,
					16,
				},
			},
			4,
		},
		{
			26,
			Low,
			dataEncoderType10To26,
			[]block{
				{
					10,
					142,
					114,
				},
				{
					2,
					143,
					115,
				},
			},
			4,
		},
		{
			26,
			Medium,
			dataEncoderType10To26,
			[]block{
				{
					19,
					74,
					46,
				},
				{
					4,
					75,
					47,
				},
			},
			4,
		},
		{
			26,
			High,
			dataEncoderType10To26,
			[]block{
				{
					28,
					50,
					22,
				},
				{
					6,
					51,
					23,
				},
			},
			4,
		},
		{
			26,
			Highest,
			dataEncoderType10To26,
			[]block{
				{
					33,
					46,
					16,
				},
				{
					4,
					47,
					17,
				},
			},
			4,
		},
		{
			27,
			Low,
			dataEncoderType27To40,
			[]block{
				{
					8,
					152,
					122,
				},
				{
					4,
					153,
					123,
				},
			},
			4,
		},
		{
			27,
			Medium,
			dataEncoderType27To40,
			[]block{
				{
					22,
					73,
					45,
				},
				{
					3,
					74,
					46,
				},
			},
			4,
		},
		{
			27,
			High,
			dataEncoderType27To40,
			[]block{
				{
					8,
					53,
					23,
				},
				{
					26,
					54,
					24,
				},
			},
			4,
		},
		{
			27,
			Highest,
			dataEncoderType27To40,
			[]block{
				{
					12,
					45,
					15,
				},
				{
					28,
					46,
					16,
				},
			},
			4,
		},
		{
			28,
			Low,
			dataEncoderType27To40,
			[]block{
				{
					3,
					147,
					117,
				},
				{
					10,
					148,
					118,
				},
			},
			3,
		},
		{
			28,
			Medium,
			dataEncoderType27To40,
			[]block{
				{
					3,
					73,
					45,
				},
				{
					23,
					74,
					46,
				},
			},
			3,
		},
		{
			28,
			High,
			dataEncoderType27To40,
			[]block{
				{
					4,
					54,
					24,
				},
				{
					31,
					55,
					25,
				},
			},
			3,
		},
		{
			28,
			Highest,
			dataEncoderType27To40,
			[]block{
				{
					11,
					45,
					15,
				},
				{
					31,
					46,
					16,
				},
			},
			3,
		},
		{
			29,
			Low,
			dataEncoderType27To40,
			[]block{
				{
					7,
					146,
					116,
				},
				{
					7,
					147,
					117,
				},
			},
			3,
		},
		{
			29,
			Medium,
			dataEncoderType27To40,
			[]block{
				{
					21,
					73,
					45,
				},
				{
					7,
					74,
					46,
				},
			},
			3,
		},
		{
			29,
			High,
			dataEncoderType27To40,
			[]block{
				{
					1,
					53,
					23,
				},
				{
					37,
					54,
					24,
				},
			},
			3,
		},
		{
			29,
			Highest,
			dataEncoderType27To40,
			[]block{
				{
					19,
					45,
					15,
				},
				{
					26,
					46,
					16,
				},
			},
			3,
		},
		{
			30,
			Low,
			dataEncoderType27To40,
			[]block{
				{
					5,
					145,
					115,
				},
				{
					10,
					146,
					116,
				},
			},
			3,
		},
		{
			30,
			Medium,
			dataEncoderType27To40,
			[]block{
				{
					19,
					75,
					47,
				},
				{
					10,
					76,
					48,
				},
			},
			3,
		},
		{
			30,
			High,
			dataEncoderType27To40,
			[]block{
				{
					15,
					54,
					24,
				},
				{
					25,
					55,
					25,
				},
			},
			3,
		},
		{
			30,
			Highest,
			dataEncoderType27To40,
			[]block{
				{
					23,
					45,
					15,
				},
				{
					25,
					46,
					16,
				},
			},
			3,
		},
		{
			31,
			Low,
			dataEncoderType27To40,
			[]block{
				{
					13,
					145,
					115,
				},
				{
					3,
					146,
					116,
				},
			},
			3,
		},
		{
			31,
			Medium,
			dataEncoderType27To40,
			[]block{
				{
					2,
					74,
					46,
				},
				{
					29,
					75,
					47,
				},
			},
			3,
		},
		{
			31,
			High,
			dataEncoderType27To40,
			[]block{
				{
					42,
					54,
					24,
				},
				{
					1,
					55,
					25,
				},
			},
			3,
		},
		{
			31,
			Highest,
			dataEncoderType27To40,
			[]block{
				{
					23,
					45,
					15,
				},
				{
					28,
					46,
					16,
				},
			},
			3,
		},
		{
			32,
			Low,
			dataEncoderType27To40,
			[]block{
				{
					17,
					145,
					115,
				},
			},
			3,
		},
		{
			32,
			Medium,
			dataEncoderType27To40,
			[]block{
				{
					10,
					74,
					46,
				},
				{
					23,
					75,
					47,
				},
			},
			3,
		},
		{
			32,
			High,
			dataEncoderType27To40,
			[]block{
				{
					10,
					54,
					24,
				},
				{
					35,
					55,
					25,
				},
			},
			3,
		},
		{
			32,
			Highest,
			dataEncoderType27To40,
			[]block{
				{
					19,
					45,
					15,
				},
				{
					35,
					46,
					16,
				},
			},
			3,
		},
		{
			33,
			Low,
			dataEncoderType27To40,
			[]block{
				{
					17,
					145,
					115,
				},
				{
					1,
					146,
					116,
				},
			},
			3,
		},
		{
			33,
			Medium,
			dataEncoderType27To40,
			[]block{
				{
					14,
					74,
					46,
				},
				{
					21,
					75,
					47,
				},
			},
			3,
		},
		{
			33,
			High,
			dataEncoderType27To40,
			[]block{
				{
					29,
					54,
					24,
				},
				{
					19,
					55,
					25,
				},
			},
			3,
		},
		{
			33,
			Highest,
			dataEncoderType27To40,
			[]block{
				{
					11,
					45,
					15,
				},
				{
					46,
					46,
					16,
				},
			},
			3,
		},
		{
			34,
			Low,
			dataEncoderType27To40,
			[]block{
				{
					13,
					145,
					115,
				},
				{
					6,
					146,
					116,
				},
			},
			3,
		},
		{
			34,
			Medium,
			dataEncoderType27To40,
			[]block{
				{
					14,
					74,
					46,
				},
				{
					23,
					75,
					47,
				},
			},
			3,
		},
		{
			34,
			High,
			dataEncoderType27To40,
			[]block{
				{
					44,
					54,
					24,
				},
				{
					7,
					55,
					25,
				},
			},
			3,
		},
		{
			34,
			Highest,
			dataEncoderType27To40,
			[]block{
				{
					59,
					46,
					16,
				},
				{
					1,
					47,
					17,
				},
			},
			3,
		},
		{
			35,
			Low,
			dataEncoderType27To40,
			[]block{
				{
					12,
					151,
					121,
				},
				{
					7,
					152,
					122,
				},
			},
			0,
		},
		{
			35,
			Medium,
			dataEncoderType27To40,
			[]block{
				{
					12,
					75,
					47,
				},
				{
					26,
					76,
					48,
				},
			},
			0,
		},
		{
			35,
			High,
			dataEncoderType27To40,
			[]block{
				{
					39,
					54,
					24,
				},
				{
					14,
					55,
					25,
				},
			},
			0,
		},
		{
			35,
			Highest,
			dataEncoderType27To40,
			[]block{
				{
					22,
					45,
					15,
				},
				{
					41,
					46,
					16,
				},
			},
			0,
		},
		{
			36,
			Low,
			dataEncoderType27To40,
			[]block{
				{
					6,
					151,
					121,
				},
				{
					14,
					152,
					122,
				},
			},
			0,
		},
		{
			36,
			Medium,
			dataEncoderType27To40,
			[]block{
				{
					6,
					75,
					47,
				},
				{
					34,
					76,
					48,
				},
			},
			0,
		},
		{
			36,
			High,
			dataEncoderType27To40,
			[]block{
				{
					46,
					54,
					24,
				},
				{
					10,
					55,
					25,
				},
			},
			0,
		},
		{
			36,
			Highest,
			dataEncoderType27To40,
			[]block{
				{
					2,
					45,
					15,
				},
				{
					64,
					46,
					16,
				},
			},
			0,
		},
		{
			37,
			Low,
			dataEncoderType27To40,
			[]block{
				{
					17,
					152,
					122,
				},
				{
					4,
					153,
					123,
				},
			},
			0,
		},
		{
			37,
			Medium,
			dataEncoderType27To40,
			[]block{
				{
					29,
					74,
					46,
				},
				{
					14,
					75,
					47,
				},
			},
			0,
		},
		{
			37,
			High,
			dataEncoderType27To40,
			[]block{
				{
					49,
					54,
					24,
				},
				{
					10,
					55,
					25,
				},
			},
			0,
		},
		{
			37,
			Highest,
			dataEncoderType27To40,
			[]block{
				{
					24,
					45,
					15,
				},
				{
					46,
					46,
					16,
				},
			},
			0,
		},
		{
			38,
			Low,
			dataEncoderType27To40,
			[]block{
				{
					4,
					152,
					122,
				},
				{
					18,
					153,
					123,
				},
			},
			0,
		},
		{
			38,
			Medium,
			dataEncoderType27To40,
			[]block{
				{
					13,
					74,
					46,
				},
				{
					32,
					75,
					47,
				},
			},
			0,
		},
		{
			38,
			High,
			dataEncoderType27To40,
			[]block{
				{
					48,
					54,
					24,
				},
				{
					14,
					55,
					25,
				},
			},
			0,
		},
		{
			38,
			Highest,
			dataEncoderType27To40,
			[]block{
				{
					42,
					45,
					15,
				},
				{
					32,
					46,
					16,
				},
			},
			0,
		},
		{
			39,
			Low,
			dataEncoderType27To40,
			[]block{
				{
					20,
					147,
					117,
				},
				{
					4,
					148,
					118,
				},
			},
			0,
		},
		{
			39,
			Medium,
			dataEncoderType27To40,
			[]block{
				{
					40,
					75,
					47,
				},
				{
					7,
					76,
					48,
				},
			},
			0,
		},
		{
			39,
			High,
			dataEncoderType27To40,
			[]block{
				{
					43,
					54,
					24,
				},
				{
					22,
					55,
					25,
				},
			},
			0,
		},
		{
			39,
			Highest,
			dataEncoderType27To40,
			[]block{
				{
					10,
					45,
					15,
				},
				{
					67,
					46,
					16,
				},
			},
			0,
		},
		{
			40,
			Low,
			dataEncoderType27To40,
			[]block{
				{
					19,
					148,
					118,
				},
				{
					6,
					149,
					119,
				},
			},
			0,
		},
		{
			40,
			Medium,
			dataEncoderType27To40,
			[]block{
				{
					18,
					75,
					47,
				},
				{
					31,
					76,
					48,
				},
			},
			0,
		},
		{
			40,
			High,
			dataEncoderType27To40,
			[]block{
				{
					34,
					54,
					24,
				},
				{
					34,
					55,
					25,
				},
			},
			0,
		},
		{
			40,
			Highest,
			dataEncoderType27To40,
			[]block{
				{
					20,
					45,
					15,
				},
				{
					61,
					46,
					16,
				},
			},
			0,
		},
	}
)

var (
	// Each QR Code contains a 15-bit Format Information value.  The 15 bits
	// consist of 5 data bits concatenated with 10 error correction bits.
	//
	// The 5 data bits consist of:
	// - 2 bits for the error correction level (L=01, M=00, G=11, H=10).
	// - 3 bits for the data mask pattern identifier.
	//
	// formatBitSequence is a mapping from the 5 data bits to the completed 15-bit
	// Format Information value.
	//
	// For example, a QR Code using error correction level L, and data mask
	// pattern identifier 001:
	//
	// 01 | 001 = 01001 = 0x9
	// formatBitSequence[0x9].qrCode = 0x72f3 = 111001011110011
	formatBitSequence = []struct {
		regular uint32
		micro   uint32
	}{
		{0x5412, 0x4445},
		{0x5125, 0x4172},
		{0x5e7c, 0x4e2b},
		{0x5b4b, 0x4b1c},
		{0x45f9, 0x55ae},
		{0x40ce, 0x5099},
		{0x4f97, 0x5fc0},
		{0x4aa0, 0x5af7},
		{0x77c4, 0x6793},
		{0x72f3, 0x62a4},
		{0x7daa, 0x6dfd},
		{0x789d, 0x68ca},
		{0x662f, 0x7678},
		{0x6318, 0x734f},
		{0x6c41, 0x7c16},
		{0x6976, 0x7921},
		{0x1689, 0x06de},
		{0x13be, 0x03e9},
		{0x1ce7, 0x0cb0},
		{0x19d0, 0x0987},
		{0x0762, 0x1735},
		{0x0255, 0x1202},
		{0x0d0c, 0x1d5b},
		{0x083b, 0x186c},
		{0x355f, 0x2508},
		{0x3068, 0x203f},
		{0x3f31, 0x2f66},
		{0x3a06, 0x2a51},
		{0x24b4, 0x34e3},
		{0x2183, 0x31d4},
		{0x2eda, 0x3e8d},
		{0x2bed, 0x3bba},
	}

	// QR Codes version 7 and higher contain an 18-bit Version Information value,
	// consisting of a 6 data bits and 12 error correction bits.
	//
	// versionBitSequence is a mapping from QR Code version to the completed
	// 18-bit Version Information value.
	//
	// For example, a QR code of version 7:
	// versionBitSequence[0x7] = 0x07c94 = 000111110010010100
	versionBitSequence = []uint32{
		0x00000,
		0x00000,
		0x00000,
		0x00000,
		0x00000,
		0x00000,
		0x00000,
		0x07c94,
		0x085bc,
		0x09a99,
		0x0a4d3,
		0x0bbf6,
		0x0c762,
		0x0d847,
		0x0e60d,
		0x0f928,
		0x10b78,
		0x1145d,
		0x12a17,
		0x13532,
		0x149a6,
		0x15683,
		0x168c9,
		0x177ec,
		0x18ec4,
		0x191e1,
		0x1afab,
		0x1b08e,
		0x1cc1a,
		0x1d33f,
		0x1ed75,
		0x1f250,
		0x209d5,
		0x216f0,
		0x228ba,
		0x2379f,
		0x24b0b,
		0x2542e,
		0x26a64,
		0x27541,
		0x28c69,
	}
)

const (
	formatInfoLengthBits  = 15
	versionInfoLengthBits = 18
)

// formatInfo returns the 15-bit Format Information value for a QR
// code.
func (v qrCodeVersion) formatInfo(maskPattern int) *bitset.Bitset {
	formatID := 0

	switch v.level {
	case Low:
		formatID = 0x08 // 0b01000
	case Medium:
		formatID = 0x00 // 0b00000
	case High:
		formatID = 0x18 // 0b11000
	case Highest:
		formatID = 0x10 // 0b10000
	default:
		log.Panicf("Invalid level %d", v.level)
	}

	if maskPattern < 0 || maskPattern > 7 {
		log.Panicf("Invalid maskPattern %d", maskPattern)
	}

	formatID |= maskPattern & 0x7

	result := bitset.New()

	result.AppendUint32(formatBitSequence[formatID].regular, formatInfoLengthBits)

	return result
}

// versionInfo returns the 18-bit Version Information value for a QR Code.
//
// Version Information is applicable only to QR Codes versions 7-40 inclusive.
// nil is returned if Version Information is not required.
func (v qrCodeVersion) versionInfo() *bitset.Bitset {
	if v.version < 7 {
		return nil
	}

	result := bitset.New()
	result.AppendUint32(versionBitSequence[v.version], 18)

	return result
}

// numDataBits returns the data capacity in bits.
func (v qrCodeVersion) numDataBits() int {
	numDataBits := 0
	for _, b := range v.block {
		numDataBits += 8 * b.numBlocks * b.numDataCodewords // 8 bits in a byte
	}

	return numDataBits
}

// chooseQRCodeVersion chooses the most suitable QR Code version for a stated
// data length in bits, the error recovery level required, and the data encoder
// used.
//
// The chosen QR Code version is the smallest version able to fit numDataBits
// and the optional terminator bits required by the specified encoder.
//
// On success the chosen QR Code version is returned.
func chooseQRCodeVersion(level RecoveryLevel, encoder *dataEncoder, numDataBits int) *qrCodeVersion {
	var chosenVersion *qrCodeVersion

	for _, v := range versions {
		if v.level != level {
			continue
		} else if v.version < encoder.minVersion {
			continue
		} else if v.version > encoder.maxVersion {
			break
		}

		numFreeBits := v.numDataBits() - numDataBits

		if numFreeBits >= 0 {
			chosenVersion = &v
			break
		}
	}

	return chosenVersion
}

func (v qrCodeVersion) numTerminatorBitsRequired(numDataBits int) int {
	numFreeBits := v.numDataBits() - numDataBits

	var numTerminatorBits int

	switch {
	case numFreeBits >= 4:
		numTerminatorBits = 4
	default:
		numTerminatorBits = numFreeBits
	}

	return numTerminatorBits
}

// numBlocks returns the number of blocks.
func (v qrCodeVersion) numBlocks() int {
	numBlocks := 0

	for _, b := range v.block {
		numBlocks += b.numBlocks
	}

	return numBlocks
}

// numBitsToPadToCodeword returns the number of bits required to pad data of
// length numDataBits upto the nearest codeword size.
func (v qrCodeVersion) numBitsToPadToCodeword(numDataBits int) int {
	if numDataBits == v.numDataBits() {
		return 0
	}

	return (8 - numDataBits%8) % 8
}

// symbolSize returns the size of the QR Code symbol in number of modules (which
// is both the width and height, since QR codes are square). The QR Code has
// size symbolSize() x symbolSize() pixels. This does not include the quiet
// zone.
func (v qrCodeVersion) symbolSize() int {
	return 21 + (v.version-1)*4
}

// quietZoneSize returns the number of pixels of border space on each side of
// the QR Code. The quiet space assists with decoding.
func (v qrCodeVersion) quietZoneSize() int {
	return 4
}

// getQRCodeVersion returns the QR Code version by version number and recovery
// level. Returns nil if the requested combination is not defined.
func getQRCodeVersion(level RecoveryLevel, version int) *qrCodeVersion {
	for _, v := range versions {
		if v.level == level && v.version == version {
			return &v
		}
	}

	return nil
}
