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

	
	
	
	
)

type (
	Option func(config)
	config interface{}
)

// WithChunk sets the chunk size for reading in json records. The default is to
// read in one row per record batch as a single object. If chunk size is set to
// a negative value, then the entire file is read as a single record batch.
// Otherwise a record batch is read in with chunk size rows per record batch until
// it reaches EOF.
func ( int) Option {
	return func( config) {
		switch cfg := .(type) {
		case *JSONReader:
			.chunk = 
		default:
			panic(fmt.Errorf("arrow/json): unknown config type %T", ))
		}
	}
}

// WithAllocator specifies the allocator to use for creating the record batches,
// if it is not called, then memory.DefaultAllocator will be used.
func ( memory.Allocator) Option {
	return func( config) {
		switch cfg := .(type) {
		case *JSONReader:
			.mem = 
		default:
			panic(fmt.Errorf("arrow/json): unknown config type %T", ))
		}
	}
}

// JSONReader is a json reader that meets the RecordReader interface definition.
//
// To read in an array of objects as a record, you can use RecordFromJSON
// which is equivalent to reading the json as a struct array whose fields are
// the columns of the record. This primarily exists to fit the RecordReader
// interface as a matching reader for the csv reader.
type JSONReader struct {
	r      *json.Decoder
	schema *arrow.Schema

	bldr *RecordBuilder

	refs atomic.Int64
	cur  arrow.RecordBatch
	err  error

	chunk int
	done  bool

	mem  memory.Allocator
	next func() bool
}

// NewJSONReader returns a json RecordReader which expects to find one json object
// per row of dataset. Using WithChunk can control how many rows are processed
// per record, which is how many objects become a single record from the file.
//
// If it is desired to write out an array of rows, then simply use RecordToStructArray
// and json.Marshal the struct array for the same effect.
func ( io.Reader,  *arrow.Schema,  ...Option) *JSONReader {
	 := &JSONReader{
		r:      json.NewDecoder(),
		schema: ,
		chunk:  1,
	}
	.refs.Add(1)

	for ,  := range  {
		()
	}

	if .mem == nil {
		.mem = memory.DefaultAllocator
	}

	.bldr = NewRecordBuilder(.mem, )
	switch {
	case .chunk < 0:
		.next = .nextall
	case .chunk > 1:
		.next = .nextn
	default:
		.next = .next1
	}
	return 
}

// Err returns the last encountered error
func ( *JSONReader) () error { return .err }

func ( *JSONReader) () *arrow.Schema { return .schema }

// RecordBatch returns the last read in record batch. The returned record batch is only valid
// until the next call to Next unless Retain is called on the record batch itself.
func ( *JSONReader) () arrow.RecordBatch { return .cur }

// Record returns the last read in record. The returned record is only valid
// until the next call to Next unless Retain is called on the record itself.
//
// Deprecated: Use [RecordBatch] instead.
func ( *JSONReader) () arrow.Record { return .RecordBatch() }

func ( *JSONReader) () {
	.refs.Add(1)
}

func ( *JSONReader) () {
	debug.Assert(.refs.Load() > 0, "too many releases")

	if .refs.Add(-1) == 0 {
		if .cur != nil {
			.cur.Release()
			.bldr.Release()
			.r = nil
		}
	}
}

// Next returns true if it read in a record, which will be available via RecordBatch
// and false if there is either an error or the end of the reader.
func ( *JSONReader) () bool {
	if .cur != nil {
		.cur.Release()
		.cur = nil
	}

	if .err != nil || .done {
		return false
	}

	return .next()
}

func ( *JSONReader) () bool {
	.err = .r.Decode(.bldr)
	if .err != nil {
		.done = true
		if errors.Is(.err, io.EOF) {
			.err = nil
		}
		return false
	}
	return true
}

func ( *JSONReader) () bool {
	for .readNext() {
	}

	.cur = .bldr.NewRecord()
	return .cur.NumRows() > 0
}

func ( *JSONReader) () bool {
	if !.readNext() {
		return false
	}

	.cur = .bldr.NewRecord()
	return true
}

func ( *JSONReader) () bool {
	 := 0

	for  := 0;  < .chunk && !.done; ,  = +1, +1 {
		if !.readNext() {
			break
		}
	}

	if  > 0 {
		.cur = .bldr.NewRecord()
	}
	return  > 0
}

var _ RecordReader = (*JSONReader)(nil)