package brotli

/* Copyright 2013 Google Inc. All Rights Reserved.

   Distributed under MIT license.
   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/

/* Block split point selection utilities. */

type blockSplit struct {
	num_types          uint
	num_blocks         uint
	types              []byte
	lengths            []uint32
	types_alloc_size   uint
	lengths_alloc_size uint
}

const (
	kMaxLiteralHistograms        uint    = 100
	kMaxCommandHistograms        uint    = 50
	kLiteralBlockSwitchCost      float64 = 28.1
	kCommandBlockSwitchCost      float64 = 13.5
	kDistanceBlockSwitchCost     float64 = 14.6
	kLiteralStrideLength         uint    = 70
	kCommandStrideLength         uint    = 40
	kSymbolsPerLiteralHistogram  uint    = 544
	kSymbolsPerCommandHistogram  uint    = 530
	kSymbolsPerDistanceHistogram uint    = 544
	kMinLengthForBlockSplitting  uint    = 128
	kIterMulForRefining          uint    = 2
	kMinItersForRefining         uint    = 100
)

func countLiterals( []command) uint {
	var  uint = 0
	/* Count how many we have. */

	for  := range  {
		 += uint([].insert_len_)
	}

	return 
}

func copyLiteralsToByteArray( []command,  []byte,  uint,  uint,  []byte) {
	var  uint = 0
	var  uint =  & 
	for  := range  {
		var  uint = uint([].insert_len_)
		if + >  {
			var  uint =  + 1 - 
			copy([:], [:][:])
			 = 0
			 += 
			 -= 
		}

		if  > 0 {
			copy([:], [:][:])
			 += 
		}

		 = uint((uint32(+) + commandCopyLen(&[])) & uint32())
	}
}

func myRand( *uint32) uint32 {
	/* Initial seed should be 7. In this case, loop length is (1 << 29). */
	* *= 16807

	return *
}

func bitCost( uint) float64 {
	if  == 0 {
		return -2.0
	} else {
		return fastLog2()
	}
}

const histogramsPerBatch = 64

const clustersPerBatch = 16

func initBlockSplit( *blockSplit) {
	.num_types = 0
	.num_blocks = 0
	.types = .types[:0]
	.lengths = .lengths[:0]
	.types_alloc_size = 0
	.lengths_alloc_size = 0
}

func splitBlock( []command,  []byte,  uint,  uint,  *encoderParams,  *blockSplit,  *blockSplit,  *blockSplit) {
	{
		var  uint = countLiterals()
		var  []byte = make([]byte, )

		/* Create a continuous array of literals. */
		copyLiteralsToByteArray(, , , , )

		/* Create the block split on the array of literals.
		   Literal histograms have alphabet size 256. */
		splitByteVectorLiteral(, , kSymbolsPerLiteralHistogram, kMaxLiteralHistograms, kLiteralStrideLength, kLiteralBlockSwitchCost, , )

		 = nil
	}
	{
		var  []uint16 = make([]uint16, len())
		/* Compute prefix codes for commands. */

		for  := range  {
			[] = [].cmd_prefix_
		}

		/* Create the block split on the array of command prefixes. */
		splitByteVectorCommand(, kSymbolsPerCommandHistogram, kMaxCommandHistograms, kCommandStrideLength, kCommandBlockSwitchCost, , )

		/* TODO: reuse for distances? */

		 = nil
	}
	{
		var  []uint16 = make([]uint16, len())
		var  uint = 0
		/* Create a continuous array of distance prefixes. */

		for  := range  {
			var  *command = &[]
			if commandCopyLen() != 0 && .cmd_prefix_ >= 128 {
				[] = .dist_prefix_ & 0x3FF
				++
			}
		}

		/* Create the block split on the array of distance prefixes. */
		splitByteVectorDistance(, , kSymbolsPerDistanceHistogram, kMaxCommandHistograms, kCommandStrideLength, kDistanceBlockSwitchCost, , )

		 = nil
	}
}