// 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 (
	"fmt"
	"strings"

	"github.com/apache/arrow/go/arrow"
)

{{range .In}}

// A type which represents an immutable sequence of {{or .QualifiedType .Type}} values.
type {{.Name}} struct {
	array
	values []{{or .QualifiedType .Type}}
}

// New{{.Name}}Data creates a new {{.Name}}.
func New{{.Name}}Data(data *Data) *{{.Name}} {
	a := &{{.Name}}{}
	a.refCount = 1
	a.setData(data)
	return a
}

// Reset resets the array for re-use.
func (a *{{.Name}}) Reset(data *Data) {
	a.setData(data)
}

// Value returns the value at the specified index.
func (a *{{.Name}}) Value(i int)      {{or .QualifiedType .Type}} { return a.values[i] }

// Values returns the values.
func (a *{{.Name}}) {{.Name}}Values() []{{or .QualifiedType .Type}} { return a.values }

// String returns a string representation of the array.
func (a *{{.Name}}) String() string {
	o := new(strings.Builder)
	o.WriteString("[")
	for i, v := range a.values {
		if i > 0 {
			fmt.Fprintf(o, " ")
		}
		switch {
		case a.IsNull(i):
			o.WriteString("(null)")
		default:
			fmt.Fprintf(o, "%v", v)
		}
	}
	o.WriteString("]")
	return o.String()
}

func (a *{{.Name}}) setData(data *Data) {
	a.array.setData(data)
	vals := data.buffers[1]
	if vals != nil {
		a.values = arrow.{{.Name}}Traits.CastFromBytes(vals.Bytes())
		beg := a.array.data.offset
		end := beg + a.array.data.length
		a.values = a.values[beg:end]
	}
}

func arrayEqual{{.Name}}(left, right *{{.Name}}) bool {
	for i := 0; i < left.Len(); i++ {
		if left.IsNull(i) {
			continue
		}
		if left.Value(i) != right.Value(i) {
			return false
		}
	}
	return true
}

{{end}}
