package builder

import (
	
	

	
	
	
)

func ( memory.Allocator,  arrow.DataType) ColumnBuilder {
	switch t := .(type) {
	case *arrow.BinaryType:
		return NewOptBinaryBuilder(arrow.BinaryTypes.Binary)
	case *arrow.Int64Type:
		return NewOptInt64Builder(arrow.PrimitiveTypes.Int64)
	case *arrow.ListType:
		return NewListBuilder(, .Elem())
	case *arrow.BooleanType:
		return NewOptBooleanBuilder(arrow.FixedWidthTypes.Boolean)
	default:
		return array.NewBuilder(, )
	}
}

func ( ColumnBuilder) error {
	switch b := .(type) {
	case *OptBinaryBuilder:
		.ResetToLength(.Len() - 1)
	case *OptInt64Builder:
		.ResetToLength(.Len() - 1)
	case *OptBooleanBuilder:
		.ResetToLength(.Len() - 1)
	case *array.Int64Builder:
		.Resize(.Len() - 1)

	case *array.StringBuilder:
		.Resize(.Len() - 1)
	case *array.BinaryBuilder:
		.Resize(.Len() - 1)
	case *array.FixedSizeBinaryBuilder:
		.Resize(.Len() - 1)
	case *array.BooleanBuilder:
		.Resize(.Len() - 1)
	case *array.BinaryDictionaryBuilder:
		.Resize(.Len() - 1)
	default:
		return fmt.Errorf("unsupported type for RollbackPrevious %T", )
	}
	return nil
}

func ( ColumnBuilder,  arrow.Array,  int) error {
	if  == nil || .IsNull() {
		.AppendNull()
		return nil
	}

	switch b := .(type) {
	case *OptBinaryBuilder:
		return .Append(.(*array.Binary).Value())
	case *OptInt64Builder:
		.Append(.(*array.Int64).Value())
	case *OptBooleanBuilder:
		.AppendSingle(.(*array.Boolean).Value())
	case *array.Int64Builder:
		.Append(.(*array.Int64).Value())
	case *array.Int32Builder:
		.Append(.(*array.Int32).Value())
	case *array.Float64Builder:
		.Append(.(*array.Float64).Value())
	case *array.Uint64Builder:
		.Append(.(*array.Uint64).Value())
	case *array.StringBuilder:
		.Append(.(*array.String).Value())
	case *array.BinaryBuilder:
		.Append(.(*array.Binary).Value())
	case *array.FixedSizeBinaryBuilder:
		.Append(.(*array.FixedSizeBinary).Value())
	case *array.BooleanBuilder:
		.Append(.(*array.Boolean).Value())
	case *array.StructBuilder:
		 := .(*array.Struct)

		.Append(true)
		for  := 0;  < .NumField(); ++ {
			if  := (.FieldBuilder(), .Field(), );  != nil {
				return fmt.Errorf("failed to append struct field: %w", )
			}
		}
	case *array.BinaryDictionaryBuilder:
		switch a := .(type) {
		case *array.Dictionary:
			switch dict := .Dictionary().(type) {
			case *array.Binary:
				if  := .Append(.Value(.GetValueIndex()));  != nil {
					return 
				}
			case *array.String:
				if  := .AppendString(.Value(.GetValueIndex()));  != nil {
					return 
				}
			default:
				return fmt.Errorf("dictionary type %T unsupported", )
			}
		default:
			return fmt.Errorf("non-dictionary array %T provided for dictionary builder", )
		}
	case *array.ListBuilder:
		return buildList(.ValueBuilder(), , , )
	case *ListBuilder:
		return buildList(.ValueBuilder(), , , )
	default:
		return fmt.Errorf("unsupported type for arrow append %T", )
	}
	return nil
}

type ListLikeBuilder interface {
	Append(bool)
}

func buildList( any,  ListLikeBuilder,  arrow.Array,  int) error {
	 := .(*array.List)
	,  := .ValueOffsets()

	 := .ListValues().Data()
	if  > int64(.Len()) ||  >  || .Offset()+int() > .Offset()+.Len() {
		return fmt.Errorf("invalid data range: start=%d end=%d for list with %v", , , .Offsets())
	}

	 := array.NewSlice(.ListValues(), , )
	defer .Release()

	switch v := .(type) {
	case *array.Int64:
		 := .(*OptInt64Builder)
		.Append(true)
		for  := 0;  < .Len(); ++ {
			.Append(.Value())
		}
	case *array.Dictionary:
		switch dict := .Dictionary().(type) {
		case *array.Binary:
			.Append(true)
			for  := 0;  < .Len(); ++ {
				switch bldr := .(type) {
				case *array.BinaryDictionaryBuilder:
					if  := .Append(.Value(.GetValueIndex()));  != nil {
						return 
					}
				default:
					return fmt.Errorf("unknown value builder type %T", )
				}
			}
		}
	case *array.Struct:
		,  := .(*array.StructBuilder)
		if ! {
			return fmt.Errorf("unsupported type for ListLikeBuilder: %T", )
		}

		.Append(true)
		for  := 0;  < .Len(); ++ {
			.Append(true)
			for  := 0;  < .NumField(); ++ {
				if  := AppendValue(.FieldBuilder(), .Field(), );  != nil {
					return 
				}
			}
		}
	default:
		return fmt.Errorf("unsupported type for List builder %T", )
	}

	return nil
}

// TODO(asubiotto): This function doesn't handle NULLs in the case of optimized
// builders.
func ( ColumnBuilder,  arrow.Array) error {
	switch b := .(type) {
	case *OptBinaryBuilder:
		 := .(*array.Binary)
		 := .ValueOffsets()
		return .AppendData(.ValueBytes(), *(*[]uint32)(unsafe.Pointer(&)))
	case *OptInt64Builder:
		.AppendData(.(*array.Int64).Int64Values())
	default:
		// TODO(asubiotto): Handle OptBooleanBuilder. It needs some way to
		// append data.
		for  := 0;  < .Len(); ++ {
			// This is an interface conversion on each call, but we should care
			// more about porting our uses of arrow builders to optimized
			// builders for exactly these use cases.
			if  := AppendValue(, , );  != nil {
				return 
			}
		}
	}
	return nil
}

func ( ColumnBuilder,  any) error {
	if  == nil {
		.AppendNull()
		return nil
	}

	switch b := .(type) {
	case *OptBinaryBuilder:
		return .Append(.([]byte))
	case *OptBooleanBuilder:
		.AppendSingle(.(bool))
	case *OptFloat64Builder:
		.Append(.(float64))
	case *OptInt32Builder:
		.Append(.(int32))
	case *OptInt64Builder:
		.Append(.(int64))
	case *array.Int64Builder:
		.Append(.(int64))
	case *array.Int32Builder:
		.Append(.(int32))
	case *array.StringBuilder:
		.Append(.(string))
	case *array.BinaryBuilder:
		.Append(.([]byte))
	case *array.FixedSizeBinaryBuilder:
		.Append(.([]byte))
	case *array.BooleanBuilder:
		.Append(.(bool))
	case *array.BinaryDictionaryBuilder:
		switch e := .(type) {
		case string:
			return .Append([]byte())
		case []byte:
			return .Append()
		default:
			return fmt.Errorf("unsupported type %T for append go value %T", , )
		}
	default:
		return fmt.Errorf("unsupported type for append go value %T", )
	}
	return nil
}