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

import (
	
	
	
	

	
)

func temporalToString( TemporalScalar) string {
	switch s := .(type) {
	case *Date32:
		return time.Unix(0, 0).UTC().AddDate(0, 0, int(.Value)).Format("2006-01-02")
	case *Date64:
		 := int(int64(.Value) / (time.Hour * 24).Milliseconds())
		return time.Unix(0, 0).UTC().AddDate(0, 0, ).Format("2006-01-02")
	case *Duration:
		return fmt.Sprint(time.Duration(.Value) * .Unit().Multiplier())
	case *Time32:
		return time.Unix(0, int64(.Value)*int64(.Unit().Multiplier())).UTC().Format("15:04:05.999")
	case *Time64:
		return time.Unix(0, int64(.Value)*int64(.Unit().Multiplier())).UTC().Format("15:04:05.999999999")
	case *Timestamp:
		return time.Unix(0, int64(.Value)*int64(.Unit().Multiplier())).UTC().Format("2006-01-02 15:04:05.999999999")
	}
	return "..."
}

type TemporalScalar interface {
	Scalar
	temporal()
}

type Duration struct {
	scalar
	Value arrow.Duration
}

func (Duration) ()                                   {}
func ( *Duration) () interface{}                       { return .Value }
func ( *Duration) ( arrow.DataType) (Scalar, error) { return castTemporal(, ) }
func ( *Duration) () string {
	if !.Valid {
		return "null"
	}
	,  := .CastTo(arrow.BinaryTypes.String)
	if  != nil {
		return "..."
	}
	return string(.(*String).Value.Bytes())
}

func ( *Duration) ( Scalar) bool {
	return .Value == .(*Duration).Value
}

func ( *Duration) () arrow.TimeUnit {
	return .DataType().(*arrow.TimestampType).Unit
}
func ( *Duration) () []byte {
	return (*[arrow.DurationSizeBytes]byte)(unsafe.Pointer(&.Value))[:]
}

func ( arrow.Duration,  arrow.DataType) *Duration {
	return &Duration{scalar{, true}, }
}

type DateScalar interface {
	TemporalScalar
	ToTime() time.Time
	date()
}

type TimeScalar interface {
	TemporalScalar
	Unit() arrow.TimeUnit
	ToTime() time.Time
	time()
}

type IntervalScalar interface {
	TemporalScalar
	interval()
}

const millisecondsInDay = (time.Hour * 24) / time.Millisecond

func castTemporal( TemporalScalar,  arrow.DataType) (Scalar, error) {
	if arrow.TypeEqual(.DataType(), ) {
		return , nil
	}

	if !.IsValid() {
		return MakeNullScalar(), nil
	}

	if ,  := numericMap[.ID()];  {
		return convertToNumeric(reflect.ValueOf(.value()), .valueType, .scalarFunc), nil
	}

	if .ID() == arrow.STRING {
		return NewStringScalar(temporalToString()), nil
	}

	switch s := .(type) {
	case DateScalar:
		if .ID() == arrow.TIMESTAMP {
			var  int64
			switch s := .(type) {
			case *Date32:
				 = int64(.Value) * int64(millisecondsInDay)
			case *Date64:
				 = int64(.Value)
			}
			return NewTimestampScalar(arrow.Timestamp(arrow.ConvertTimestampValue(arrow.Millisecond, .(*arrow.TimestampType).Unit, )), ), nil
		}

		switch s := .(type) {
		case *Date32:
			if .ID() == arrow.DATE64 {
				return NewDate64Scalar(arrow.Date64(.Value) * arrow.Date64(millisecondsInDay)), nil
			}
		case *Date64:
			if .ID() == arrow.DATE32 {
				return NewDate32Scalar(arrow.Date32(.Value / arrow.Date64(millisecondsInDay))), nil
			}
		}
	case *Timestamp:
		switch to := .(type) {
		case *arrow.TimestampType:
			return NewTimestampScalar(arrow.Timestamp(arrow.ConvertTimestampValue(.Unit(), .Unit, int64(.Value))), ), nil
		case *arrow.Date32Type:
			 := arrow.ConvertTimestampValue(.Unit(), arrow.Millisecond, int64(.Value))
			return NewDate32Scalar(arrow.Date32( / int64(millisecondsInDay))), nil
		case *arrow.Date64Type:
			 := arrow.ConvertTimestampValue(.Unit(), arrow.Millisecond, int64(.Value))
			return NewDate64Scalar(arrow.Date64( - %int64(millisecondsInDay))), nil
		}
	case TimeScalar:
		switch to := .(type) {
		case *arrow.Time32Type:
			return NewTime32Scalar(arrow.Time32(arrow.ConvertTimestampValue(.Unit(), .Unit, int64(.value().(arrow.Time64)))), ), nil
		case *arrow.Time64Type:
			return NewTime64Scalar(arrow.Time64(arrow.ConvertTimestampValue(.Unit(), .Unit, int64(.value().(arrow.Time32)))), ), nil
		}

	case *Duration:
		switch to := .(type) {
		case *arrow.StringType:

		case *arrow.DurationType:
			return NewDurationScalar(arrow.Duration(arrow.ConvertTimestampValue(.Unit(), .Unit, int64(.Value))), ), nil
		}
	}

	return nil, fmt.Errorf("")
}

type Date32 struct {
	scalar
	Value arrow.Date32
}

func (Date32) ()             {}
func (Date32) ()                 {}
func ( *Date32) () interface{} { return .Value }
func ( *Date32) () []byte {
	return (*[arrow.Date32SizeBytes]byte)(unsafe.Pointer(&.Value))[:]
}
func ( *Date32) ( Scalar) bool {
	return .Value == .(*Date32).Value
}
func ( *Date32) ( arrow.DataType) (Scalar, error) { return castTemporal(, ) }
func ( *Date32) () string {
	if !.Valid {
		return "null"
	}
	,  := .CastTo(arrow.BinaryTypes.String)
	if  != nil {
		return "..."
	}
	return string(.(*String).Value.Bytes())
}
func ( *Date32) () time.Time {
	return .Value.ToTime()
}

func ( arrow.Date32) *Date32 {
	return &Date32{scalar{arrow.FixedWidthTypes.Date32, true}, }
}

type Date64 struct {
	scalar
	Value arrow.Date64
}

func (Date64) ()                                   {}
func (Date64) ()                                       {}
func ( *Date64) () interface{}                       { return .Value }
func ( *Date64) ( arrow.DataType) (Scalar, error) { return castTemporal(, ) }
func ( *Date64) () []byte {
	return (*[arrow.Date64SizeBytes]byte)(unsafe.Pointer(&.Value))[:]
}
func ( *Date64) ( Scalar) bool {
	return .Value == .(*Date64).Value
}
func ( *Date64) () string {
	if !.Valid {
		return "null"
	}
	,  := .CastTo(arrow.BinaryTypes.String)
	if  != nil {
		return "..."
	}
	return string(.(*String).Value.Bytes())
}
func ( *Date64) () time.Time {
	return .Value.ToTime()
}

func ( arrow.Date64) *Date64 {
	return &Date64{scalar{arrow.FixedWidthTypes.Date64, true}, }
}

type Time32 struct {
	scalar
	Value arrow.Time32
}

func (Time32) ()                                   {}
func (Time32) ()                                       {}
func ( *Time32) () interface{}                       { return .Value }
func ( *Time32) ( arrow.DataType) (Scalar, error) { return castTemporal(, ) }
func ( *Time32) () arrow.TimeUnit {
	return .DataType().(*arrow.Time32Type).Unit
}
func ( *Time32) ( Scalar) bool {
	return .Value == .(*Time32).Value
}
func ( *Time32) () string {
	if !.Valid {
		return "null"
	}
	,  := .CastTo(arrow.BinaryTypes.String)
	if  != nil {
		return "..."
	}
	return string(.(*String).Value.Bytes())
}

func ( *Time32) () []byte {
	return (*[arrow.Time32SizeBytes]byte)(unsafe.Pointer(&.Value))[:]
}

func ( *Time32) () time.Time {
	return .Value.ToTime(.Unit())
}

func ( arrow.Time32,  arrow.DataType) *Time32 {
	return &Time32{scalar{, true}, }
}

type Time64 struct {
	scalar
	Value arrow.Time64
}

func (Time64) ()                                   {}
func (Time64) ()                                       {}
func ( *Time64) () interface{}                       { return .Value }
func ( *Time64) ( arrow.DataType) (Scalar, error) { return castTemporal(, ) }
func ( *Time64) () arrow.TimeUnit {
	return .DataType().(*arrow.Time64Type).Unit
}
func ( *Time64) () []byte {
	return (*[arrow.Time64SizeBytes]byte)(unsafe.Pointer(&.Value))[:]
}
func ( *Time64) ( Scalar) bool {
	return .Value == .(*Time64).Value
}
func ( *Time64) () string {
	if !.Valid {
		return "null"
	}
	,  := .CastTo(arrow.BinaryTypes.String)
	if  != nil {
		return "..."
	}
	return string(.(*String).Value.Bytes())
}

func ( *Time64) () time.Time {
	return .Value.ToTime(.Unit())
}

func ( arrow.Time64,  arrow.DataType) *Time64 {
	return &Time64{scalar{, true}, }
}

type Timestamp struct {
	scalar
	Value arrow.Timestamp
}

func (Timestamp) ()                                   {}
func (Timestamp) ()                                       {}
func ( *Timestamp) () interface{}                       { return .Value }
func ( *Timestamp) ( arrow.DataType) (Scalar, error) { return castTemporal(, ) }
func ( *Timestamp) () arrow.TimeUnit {
	return .DataType().(*arrow.TimestampType).Unit
}
func ( *Timestamp) () []byte {
	return (*[arrow.TimestampSizeBytes]byte)(unsafe.Pointer(&.Value))[:]
}
func ( *Timestamp) ( Scalar) bool {
	return .Value == .(*Timestamp).Value
}
func ( *Timestamp) () string {
	if !.Valid {
		return "null"
	}
	,  := .CastTo(arrow.BinaryTypes.String)
	if  != nil {
		return "..."
	}
	return string(.(*String).Value.Bytes())
}

func ( *Timestamp) () time.Time {
	return .Value.ToTime(.Unit())
}

func ( arrow.Timestamp,  arrow.DataType) *Timestamp {
	return &Timestamp{scalar{, true}, }
}

type MonthInterval struct {
	scalar
	Value arrow.MonthInterval
}

func (MonthInterval) ()             {}
func (MonthInterval) ()             {}
func ( *MonthInterval) () interface{} { return .Value }
func ( *MonthInterval) ( arrow.DataType) (Scalar, error) {
	if !.Valid {
		return MakeNullScalar(), nil
	}

	if !arrow.TypeEqual(.DataType(), ) {
		return nil, fmt.Errorf("non-null monthinterval scalar cannot be cast to anything other than monthinterval")
	}

	return , nil
}
func ( *MonthInterval) () string {
	if !.Valid {
		return "null"
	}
	,  := .CastTo(arrow.BinaryTypes.String)
	if  != nil {
		return "..."
	}
	return string(.(*String).Value.Bytes())
}
func ( *MonthInterval) ( Scalar) bool {
	return .Value == .(*MonthInterval).Value
}
func ( *MonthInterval) () []byte {
	return (*[arrow.MonthIntervalSizeBytes]byte)(unsafe.Pointer(&.Value))[:]
}

func ( arrow.MonthInterval) *MonthInterval {
	return &MonthInterval{scalar{arrow.FixedWidthTypes.MonthInterval, true}, }
}

type DayTimeInterval struct {
	scalar
	Value arrow.DayTimeInterval
}

func (DayTimeInterval) ()             {}
func (DayTimeInterval) ()             {}
func ( *DayTimeInterval) () interface{} { return .Value }
func ( *DayTimeInterval) () []byte {
	return (*[arrow.DayTimeIntervalSizeBytes]byte)(unsafe.Pointer(&.Value))[:]
}
func ( *DayTimeInterval) () string {
	if !.Valid {
		return "null"
	}
	,  := .CastTo(arrow.BinaryTypes.String)
	if  != nil {
		return "..."
	}
	return string(.(*String).Value.Bytes())
}

func ( *DayTimeInterval) ( arrow.DataType) (Scalar, error) {
	if !.Valid {
		return MakeNullScalar(), nil
	}

	if !arrow.TypeEqual(.DataType(), ) {
		return nil, fmt.Errorf("non-null daytimeinterval scalar cannot be cast to anything other than monthinterval")
	}

	return , nil
}

func ( *DayTimeInterval) ( Scalar) bool {
	return .Value == .(*DayTimeInterval).Value
}

func ( arrow.DayTimeInterval) *DayTimeInterval {
	return &DayTimeInterval{scalar{arrow.FixedWidthTypes.DayTimeInterval, true}, }
}

type MonthDayNanoInterval struct {
	scalar
	Value arrow.MonthDayNanoInterval
}

func (MonthDayNanoInterval) ()             {}
func (MonthDayNanoInterval) ()             {}
func ( *MonthDayNanoInterval) () interface{} { return .Value }
func ( *MonthDayNanoInterval) () []byte {
	return (*[arrow.MonthDayNanoIntervalSizeBytes]byte)(unsafe.Pointer(&.Value))[:]
}
func ( *MonthDayNanoInterval) () string {
	if !.Valid {
		return "null"
	}
	,  := .CastTo(arrow.BinaryTypes.String)
	if  != nil {
		return "..."
	}
	return string(.(*String).Value.Bytes())
}

func ( *MonthDayNanoInterval) ( arrow.DataType) (Scalar, error) {
	if !.Valid {
		return MakeNullScalar(), nil
	}

	if !arrow.TypeEqual(.DataType(), ) {
		return nil, fmt.Errorf("non-null month_day_nano_interval scalar cannot be cast to anything other than monthinterval")
	}

	return , nil
}

func ( *MonthDayNanoInterval) ( Scalar) bool {
	return .Value == .(*MonthDayNanoInterval).Value
}

func ( arrow.MonthDayNanoInterval) *MonthDayNanoInterval {
	return &MonthDayNanoInterval{scalar{arrow.FixedWidthTypes.MonthDayNanoInterval, true}, }
}

var (
	_ Scalar = (*Date32)(nil)
)