// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.

package array

import (
	
	
	

	
	
	
	
	
)

// FixedSizeList represents an immutable sequence of N array values.
type FixedSizeList struct {
	array
	n      int32
	values arrow.Array
}

var _ ListLike = (*FixedSizeList)(nil)

// NewFixedSizeListData returns a new List array value, from data.
func ( arrow.ArrayData) *FixedSizeList {
	 := &FixedSizeList{}
	.refCount.Add(1)
	.setData(.(*Data))
	return 
}

func ( *FixedSizeList) () arrow.Array { return .values }

func ( *FixedSizeList) ( int) string {
	if .IsNull() {
		return NullValueStr
	}
	return string(.GetOneForMarshal().(json.RawMessage))
}

func ( *FixedSizeList) () string {
	 := new(strings.Builder)
	.WriteString("[")
	for  := 0;  < .Len(); ++ {
		if  > 0 {
			.WriteString(" ")
		}
		if !.IsValid() {
			.WriteString(NullValueStr)
			continue
		}
		 := .newListValue()
		fmt.Fprintf(, "%v", )
		.Release()
	}
	.WriteString("]")
	return .String()
}

func ( *FixedSizeList) ( int) arrow.Array {
	,  := .ValueOffsets()
	return NewSlice(.values, , )
}

func ( *FixedSizeList) ( *Data) {
	.array.setData()
	.n = .DataType().(*arrow.FixedSizeListType).Len()
	.values = MakeFromData(.childData[0])
}

func arrayEqualFixedSizeList(,  *FixedSizeList) bool {
	for  := 0;  < .Len(); ++ {
		if .IsNull() {
			continue
		}
		 := func() bool {
			 := .newListValue()
			defer .Release()
			 := .newListValue()
			defer .Release()
			return Equal(, )
		}()
		if ! {
			return false
		}
	}
	return true
}

// Len returns the number of elements in the array.
func ( *FixedSizeList) () int { return .array.Len() }

func ( *FixedSizeList) ( int) (,  int64) {
	 := int64(.n)
	 := int64(.data.offset)
	,  = (+int64())*, (+int64(+1))*
	return
}

func ( *FixedSizeList) () {
	.array.Retain()
	.values.Retain()
}

func ( *FixedSizeList) () {
	.array.Release()
	.values.Release()
}

func ( *FixedSizeList) ( int) interface{} {
	if .IsNull() {
		return nil
	}
	 := .newListValue()
	defer .Release()
	,  := json.Marshal()
	if  != nil {
		panic()
	}

	return json.RawMessage()
}

func ( *FixedSizeList) () ([]byte, error) {
	var  bytes.Buffer
	 := json.NewEncoder(&)

	.WriteByte('[')
	for  := 0;  < .Len(); ++ {
		if  != 0 {
			.WriteByte(',')
		}
		if .IsNull() {
			.Encode(nil)
			continue
		}

		 := .newListValue()
		if  := .Encode();  != nil {
			return nil, 
		}
		.Release()
	}
	.WriteByte(']')
	return .Bytes(), nil
}

type FixedSizeListBuilder struct {
	baseListBuilder
	n int32 // number of elements in the fixed-size list.
}

// NewFixedSizeListBuilder returns a builder, using the provided memory allocator.
// The created list builder will create a list whose elements will be of type etype.
func ( memory.Allocator,  int32,  arrow.DataType) *FixedSizeListBuilder {
	 := &FixedSizeListBuilder{
		baseListBuilder{
			builder: builder{mem: },
			values:  NewBuilder(, ),
			dt:      arrow.FixedSizeListOf(, ),
		},
		,
	}
	.refCount.Add(1)
	return 
}

// NewFixedSizeListBuilderWithField returns a builder similarly to
// NewFixedSizeListBuilder, but it accepts a child rather than just a datatype
// to ensure nullability context is preserved.
func ( memory.Allocator,  int32,  arrow.Field) *FixedSizeListBuilder {
	 := &FixedSizeListBuilder{
		baseListBuilder{
			builder: builder{mem: },
			values:  NewBuilder(, .Type),
			dt:      arrow.FixedSizeListOfField(, ),
		},
		,
	}

	.refCount.Add(1)
	return 
}

func ( *FixedSizeListBuilder) () arrow.DataType { return .dt }

// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
func ( *FixedSizeListBuilder) () {
	debug.Assert(.refCount.Load() > 0, "too many releases")

	if .refCount.Add(-1) == 0 {
		if .nullBitmap != nil {
			.nullBitmap.Release()
			.nullBitmap = nil
		}
		if .values != nil {
			.values.Release()
			.values = nil
		}
	}
}

func ( *FixedSizeListBuilder) ( bool) {
	.Reserve(1)
	.unsafeAppendBoolToBitmap()
}

// AppendNull will append null values to the underlying values by itself
func ( *FixedSizeListBuilder) () {
	.Reserve(1)
	.unsafeAppendBoolToBitmap(false)
	// require to append this due to value indexes
	for  := int32(0);  < .n; ++ {
		.values.AppendNull()
	}
}

// AppendNulls will append n null values to the underlying values by itself
func ( *FixedSizeListBuilder) ( int) {
	for  := 0;  < ; ++ {
		.AppendNull()
	}
}

func ( *FixedSizeListBuilder) () {
	.Append(true)
	for  := int32(0);  < .n; ++ {
		.values.AppendEmptyValue()
	}
}

func ( *FixedSizeListBuilder) ( int) {
	for  := 0;  < ; ++ {
		.AppendEmptyValue()
	}
}

func ( *FixedSizeListBuilder) ( []bool) {
	.Reserve(len())
	.unsafeAppendBoolsToBitmap(, len())
}

func ( *FixedSizeListBuilder) ( bool) {
	if  {
		bitutil.SetBit(.nullBitmap.Bytes(), .length)
	} else {
		.nulls++
	}
	.length++
}

func ( *FixedSizeListBuilder) ( int) {
	.builder.init()
}

// Reserve ensures there is enough space for appending n elements
// by checking the capacity and calling Resize if necessary.
func ( *FixedSizeListBuilder) ( int) {
	.reserve(, .Resize)
}

// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(),
// additional memory will be allocated. If n is smaller, the allocated memory may reduced.
func ( *FixedSizeListBuilder) ( int) {
	if  < minBuilderCapacity {
		 = minBuilderCapacity
	}

	if .capacity == 0 {
		.init()
	} else {
		.resize(, .builder.init)
	}
}

func ( *FixedSizeListBuilder) () Builder {
	return .values
}

// NewArray creates a List array from the memory buffers used by the builder and resets the FixedSizeListBuilder
// so it can be used to build a new array.
func ( *FixedSizeListBuilder) () arrow.Array {
	return .NewListArray()
}

// NewListArray creates a List array from the memory buffers used by the builder and resets the FixedSizeListBuilder
// so it can be used to build a new array.
func ( *FixedSizeListBuilder) () ( *FixedSizeList) {
	 := .newData()
	 = NewFixedSizeListData()
	.Release()
	return
}

func ( *FixedSizeListBuilder) () ( *Data) {
	 := .values.NewArray()
	defer .Release()

	 = NewData(
		.dt, .length,
		[]*memory.Buffer{.nullBitmap},
		[]arrow.ArrayData{.Data()},
		.nulls,
		0,
	)
	.reset()

	return
}

func ( *FixedSizeListBuilder) ( string) error {
	if  == NullValueStr {
		.AppendNull()
		return nil
	}
	 := json.NewDecoder(strings.NewReader())
	return .UnmarshalOne()
}

func ( *FixedSizeListBuilder) ( *json.Decoder) error {
	,  := .Token()
	if  != nil {
		return 
	}

	switch  {
	case json.Delim('['):
		.Append(true)
		if  := .values.Unmarshal();  != nil {
			return 
		}
		// consume ']'
		,  := .Token()
		return 
	case nil:
		.AppendNull()
	default:
		return &json.UnmarshalTypeError{
			Value:  fmt.Sprint(),
			Struct: .dt.String(),
		}
	}

	return nil
}

func ( *FixedSizeListBuilder) ( *json.Decoder) error {
	for .More() {
		if  := .UnmarshalOne();  != nil {
			return 
		}
	}
	return nil
}

func ( *FixedSizeListBuilder) ( []byte) error {
	 := json.NewDecoder(bytes.NewReader())
	,  := .Token()
	if  != nil {
		return 
	}

	if ,  := .(json.Delim); ! ||  != '[' {
		return fmt.Errorf("fixed size list builder must unpack from json array, found %s", )
	}

	return .Unmarshal()
}

var (
	_ arrow.Array = (*FixedSizeList)(nil)
	_ Builder     = (*FixedSizeListBuilder)(nil)
)