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

//go:build go1.18

package kernels

import (
	

	
	
	
	
)

var (
	unsignedIntTypes = []arrow.DataType{
		arrow.PrimitiveTypes.Uint8,
		arrow.PrimitiveTypes.Uint16,
		arrow.PrimitiveTypes.Uint32,
		arrow.PrimitiveTypes.Uint64,
	}
	signedIntTypes = []arrow.DataType{
		arrow.PrimitiveTypes.Int8,
		arrow.PrimitiveTypes.Int16,
		arrow.PrimitiveTypes.Int32,
		arrow.PrimitiveTypes.Int64,
	}
	intTypes      = append(unsignedIntTypes, signedIntTypes...)
	floatingTypes = []arrow.DataType{
		arrow.PrimitiveTypes.Float32,
		arrow.PrimitiveTypes.Float64,
	}
	numericTypes = append(intTypes, floatingTypes...)
	// binary types without fixedsize binary
	baseBinaryTypes = []arrow.DataType{
		arrow.BinaryTypes.Binary,
		arrow.BinaryTypes.LargeBinary,
		arrow.BinaryTypes.String,
		arrow.BinaryTypes.LargeString}
	primitiveTypes = append(append([]arrow.DataType{arrow.Null,
		arrow.FixedWidthTypes.Date32, arrow.FixedWidthTypes.Date64},
		numericTypes...), baseBinaryTypes...)
)

//go:generate stringer -type=CompareOperator -linecomment

type CompareOperator int8

const (
	CmpEQ CompareOperator = iota // equal
	CmpNE                        // not_equal
	CmpGT                        // greater
	CmpGE                        // greater_equal
	CmpLT                        // less
	CmpLE                        // less_equal
)

type simpleBinaryKernel interface {
	Call(*exec.KernelCtx, *exec.ArraySpan, *exec.ArraySpan, *exec.ExecResult) error
	CallScalarLeft(*exec.KernelCtx, scalar.Scalar, *exec.ArraySpan, *exec.ExecResult) error
}

type commutativeBinaryKernel[ simpleBinaryKernel] struct{}

func (commutativeBinaryKernel[]) ( *exec.KernelCtx,  *exec.ArraySpan,  scalar.Scalar,  *exec.ExecResult) error {
	var  
	return .CallScalarLeft(, , , )
}

type SimpleBinaryKernel interface {
	simpleBinaryKernel
	CallScalarRight(*exec.KernelCtx, *exec.ArraySpan, scalar.Scalar, *exec.ExecResult) error
}

func [ SimpleBinaryKernel]( *exec.KernelCtx,  *exec.ExecSpan,  *exec.ExecResult) error {
	if .Len == 0 {
		return nil
	}

	var  
	if .Values[0].IsArray() {
		if .Values[1].IsArray() {
			return .Call(, &.Values[0].Array, &.Values[1].Array, )
		}
		return .CallScalarRight(, &.Values[0].Array, .Values[1].Scalar, )
	}

	if .Values[1].IsArray() {
		return .CallScalarLeft(, .Values[0].Scalar, &.Values[1].Array, )
	}

	debug.Assert(false, "should be unreachable")
	return fmt.Errorf("%w: should be unreachable", arrow.ErrInvalid)
}