// 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 (
	
	
	
	

	
	
	
	
	
)

// Struct represents an ordered sequence of relative types.
type Struct struct {
	array
	fields []arrow.Array
}

// NewStructArray constructs a new Struct Array out of the columns passed
// in and the field names. The length of all cols must be the same and
// there should be the same number of columns as names.
func ( []arrow.Array,  []string) (*Struct, error) {
	return NewStructArrayWithNulls(, , nil, 0, 0)
}

// NewStructArrayWithFields builds a new Struct Array using the passed columns
// and provided fields. As opposed to NewStructArray, this allows you to provide
// the full fields to utilize for the struct column instead of just the names.
func ( []arrow.Array,  []arrow.Field) (*Struct, error) {
	return NewStructArrayWithFieldsAndNulls(, , nil, 0, 0)
}

// NewStructArrayWithFieldsAndNulls is like NewStructArrayWithFields as a convenience function,
// but also takes in a null bitmap, the number of nulls, and an optional offset
// to use for creating the Struct Array.
func ( []arrow.Array,  []arrow.Field,  *memory.Buffer,  int,  int) (*Struct, error) {
	if len() != len() {
		return nil, fmt.Errorf("%w: mismatching number of fields and child arrays", arrow.ErrInvalid)
	}
	if len() == 0 {
		return nil, fmt.Errorf("%w: can't infer struct array length with 0 child arrays", arrow.ErrInvalid)
	}

	 := [0].Len()
	 := make([]arrow.ArrayData, len())
	for ,  := range  {
		if  != .Len() {
			return nil, fmt.Errorf("%w: mismatching child array lengths", arrow.ErrInvalid)
		}
		if !arrow.TypeEqual([].Type, .DataType()) {
			return nil, fmt.Errorf("%w: mismatching data type for child #%d, field says '%s', got '%s'",
				arrow.ErrInvalid, , [].Type, .DataType())
		}

		[] = .Data()
	}

	if  == nil {
		if  > 0 {
			return nil, fmt.Errorf("%w: null count is greater than 0 but null bitmap is nil", arrow.ErrInvalid)
		}
		 = 0
	}

	 := NewData(arrow.StructOf(...), -, []*memory.Buffer{}, , , )
	defer .Release()
	return NewStructData(), nil
}

// NewStructArrayWithNulls is like NewStructArray as a convenience function,
// but also takes in a null bitmap, the number of nulls, and an optional offset
// to use for creating the Struct Array.
func ( []arrow.Array,  []string,  *memory.Buffer,  int,  int) (*Struct, error) {
	if len() != len() {
		return nil, fmt.Errorf("%w: mismatching number of fields and child arrays", arrow.ErrInvalid)
	}
	if len() == 0 {
		return nil, fmt.Errorf("%w: can't infer struct array length with 0 child arrays", arrow.ErrInvalid)
	}
	 := [0].Len()
	 := make([]arrow.ArrayData, len())
	 := make([]arrow.Field, len())
	for ,  := range  {
		if  != .Len() {
			return nil, fmt.Errorf("%w: mismatching child array lengths", arrow.ErrInvalid)
		}
		[] = .Data()
		[].Name = []
		[].Type = .DataType()
		[].Nullable = true
	}
	 := NewData(arrow.StructOf(...), , []*memory.Buffer{}, , , )
	defer .Release()
	return NewStructData(), nil
}

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

func ( *Struct) () int           { return len(.fields) }
func ( *Struct) ( int) arrow.Array { return .fields[] }

// ValueStr returns the string representation (as json) of the value at index i.
func ( *Struct) ( int) string {
	if .IsNull() {
		return NullValueStr
	}

	,  := json.Marshal(.GetOneForMarshal())
	if  != nil {
		panic()
	}
	return string()
}

func ( *Struct) () string {
	 := new(strings.Builder)
	.WriteString("{")

	 := .NullBitmapBytes()
	for ,  := range .fields {
		if  > 0 {
			.WriteString(" ")
		}
		if arrow.IsUnion(.DataType().ID()) {
			fmt.Fprintf(, "%v", )
			continue
		} else if !bytes.Equal(, .NullBitmapBytes()) {
			 := .newStructFieldWithParentValidityMask()
			fmt.Fprintf(, "%v", )
			.Release()
			continue
		}
		fmt.Fprintf(, "%v", )
	}
	.WriteString("}")
	return .String()
}

// newStructFieldWithParentValidityMask returns the Interface at fieldIndex
// with a nullBitmapBytes adjusted according on the parent struct nullBitmapBytes.
// From the docs:
//
//	"When reading the struct array the parent validity bitmap takes priority."
func ( *Struct) ( int) arrow.Array {
	 := .Field()
	 := .NullBitmapBytes()
	 := make([]byte, len())
	copy(, )
	for  := 0;  < .Len(); ++ {
		if .IsNull() {
			bitutil.ClearBit(, )
		}
	}
	 := NewSliceData(.Data(), 0, int64(.Len())).(*Data)
	defer .Release()
	 := make([]*memory.Buffer, len(.Buffers()))
	copy(, .buffers)
	[0].Release()
	[0] = memory.NewBufferBytes()
	.buffers = 
	 := MakeFromData()
	return 
}

func ( *Struct) ( *Data) {
	.array.setData()
	.fields = make([]arrow.Array, len(.childData))
	for ,  := range .childData {
		if .offset != 0 || .Len() != .length {
			 := NewSliceData(, int64(.offset), int64(.offset+.length))
			.fields[] = MakeFromData()
			.Release()
		} else {
			.fields[] = MakeFromData()
		}
	}
}

func ( *Struct) ( int) interface{} {
	if .IsNull() {
		return nil
	}

	 := make(map[string]interface{})
	 := .data.dtype.(*arrow.StructType).Fields()
	for ,  := range .fields {
		[[].Name] = .GetOneForMarshal()
	}
	return 
}

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

	.WriteByte('[')
	for  := 0;  < .Len(); ++ {
		if  != 0 {
			.WriteByte(',')
		}
		if  := .Encode(.GetOneForMarshal());  != nil {
			return nil, 
		}
	}
	.WriteByte(']')
	return .Bytes(), nil
}

func arrayEqualStruct(,  *Struct) bool {
	for ,  := range .fields {
		 := .fields[]
		if !Equal(, ) {
			return false
		}
	}
	return true
}

func ( *Struct) () {
	.array.Retain()
	for ,  := range .fields {
		.Retain()
	}
}

func ( *Struct) () {
	.array.Release()
	for ,  := range .fields {
		.Release()
	}
}

type StructBuilder struct {
	builder

	dtype  arrow.DataType
	fields []Builder
}

// NewStructBuilder returns a builder, using the provided memory allocator.
func ( memory.Allocator,  *arrow.StructType) *StructBuilder {
	 := &StructBuilder{
		builder: builder{mem: },
		dtype:   ,
		fields:  make([]Builder, .NumFields()),
	}
	.refCount.Add(1)

	for ,  := range .Fields() {
		.fields[] = NewBuilder(.mem, .Type)
	}
	return 
}

func ( *StructBuilder) () arrow.DataType {
	 := make([]arrow.Field, len(.fields))
	copy(, .dtype.(*arrow.StructType).Fields())
	for ,  := range .fields {
		[].Type = .Type()
	}
	return arrow.StructOf(...)
}

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

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

		for ,  := range .fields {
			.Release()
		}
	}
}

func ( *StructBuilder) ( bool) {
	// Intentionally not calling `Reserve` as it will recursively call
	// `Reserve` on the child builders, which during profiling has shown to be
	// very expensive due to iterating over children, dynamic dispatch and all
	// other code that gets executed even if previously `Reserve` was called to
	// preallocate. Not calling `Reserve` has no downsides as when appending to
	// the underlying children they already ensure they have enough space
	// reserved. The only thing we must do is ensure we have enough space in
	// the validity bitmap of the struct builder itself.
	.reserve(1, .resizeHelper)
	.unsafeAppendBoolToBitmap()
	if ! {
		for ,  := range .fields {
			.AppendNull()
		}
	}
}

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

func ( *StructBuilder) () { .Append(false) }

func ( *StructBuilder) ( int) {
	for  := 0;  < ; ++ {
		.AppendNull()
	}
}

func ( *StructBuilder) () {
	.Append(true)
	for ,  := range .fields {
		.AppendEmptyValue()
	}
}

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

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

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

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

// 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 ( *StructBuilder) ( int) {
	.resizeHelper()
	for ,  := range .fields {
		.Resize()
	}
}

func ( *StructBuilder) ( int) {
	if  < minBuilderCapacity {
		 = minBuilderCapacity
	}

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

func ( *StructBuilder) () int              { return len(.fields) }
func ( *StructBuilder) ( int) Builder { return .fields[] }

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

// NewStructArray creates a Struct array from the memory buffers used by the builder and resets the StructBuilder
// so it can be used to build a new array.
func ( *StructBuilder) () ( *Struct) {
	 := .newData()
	 = NewStructData()
	.Release()
	return
}

func ( *StructBuilder) () ( *Data) {
	 := make([]arrow.ArrayData, len(.fields))
	for ,  := range .fields {
		 := .NewArray()
		defer .Release()
		[] = .Data()
	}

	 = NewData(
		.Type(), .length,
		[]*memory.Buffer{
			.nullBitmap,
		},
		,
		.nulls,
		0,
	)
	.reset()

	return
}

func ( *StructBuilder) ( string) error {
	if  == NullValueStr {
		.AppendNull()
		return nil
	}

	if !strings.HasPrefix(, "{") && !strings.HasSuffix(, "}") {
		return fmt.Errorf("%w: invalid string for struct should be be of form: {*}", arrow.ErrInvalid)
	}
	 := json.NewDecoder(strings.NewReader())
	return .UnmarshalOne()
}

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

	switch  {
	case json.Delim('{'):
		.Append(true)
		 := make(map[string]bool)
		for .More() {
			,  := .Token()
			if  != nil {
				return 
			}

			,  := .(string)
			if ! {
				return errors.New("missing key")
			}

			if [] {
				return fmt.Errorf("key %s is specified twice", )
			}

			[] = true

			,  := .dtype.(*arrow.StructType).FieldIdx()
			if ! {
				var  interface{}
				if  := .Decode(&);  != nil {
					return 
				}
				continue
			}

			if  := .fields[].UnmarshalOne();  != nil {
				return 
			}
		}

		// Append null values to all optional fields that were not presented in the json input
		for ,  := range .dtype.(*arrow.StructType).Fields() {
			if !.Nullable {
				continue
			}
			,  := .dtype.(*arrow.StructType).FieldIdx(.Name)
			if ,  := [.Name]; ! {
				.fields[].AppendNull()
			}
		}

		// consume '}'
		,  := .Token()
		return 
	case nil:
		.AppendNull()
	default:
		return &json.UnmarshalTypeError{
			Offset: .InputOffset(),
			Struct: fmt.Sprint(.dtype),
		}
	}
	return nil
}

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

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

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

	return .Unmarshal()
}

var (
	_ arrow.Array = (*Struct)(nil)
	_ Builder     = (*StructBuilder)(nil)
)