package avro

import (
	
	
	
)

// ReadNext reads the next Avro element as a generic interface.
func ( *Reader) ( Schema) any {
	var  LogicalSchema
	,  := .(LogicalTypeSchema)
	if  {
		 = .Logical()
	}

	switch .Type() {
	case Boolean:
		return .ReadBool()
	case Int:
		if  != nil {
			switch .Type() {
			case Date:
				 := .ReadInt()
				 := int64() * int64(24*time.Hour/time.Second)
				return time.Unix(, 0).UTC()

			case TimeMillis:
				return time.Duration(.ReadInt()) * time.Millisecond
			}
		}
		return int(.ReadInt())
	case Long:
		if  != nil {
			switch .Type() {
			case TimeMicros:
				return time.Duration(.ReadLong()) * time.Microsecond

			case TimestampMillis:
				 := .ReadLong()
				 :=  / 1e3
				 := ( - *1e3) * 1e6
				return time.Unix(, ).UTC()

			case TimestampMicros:
				 := .ReadLong()
				 :=  / 1e6
				 := ( - *1e6) * 1e3
				return time.Unix(, ).UTC()
			}
		}
		return .ReadLong()
	case Float:
		return .ReadFloat()
	case Double:
		return .ReadDouble()
	case String:
		return .ReadString()
	case Bytes:
		if  != nil && .Type() == Decimal {
			 := .(*DecimalLogicalSchema)
			return ratFromBytes(.ReadBytes(), .Scale())
		}
		return .ReadBytes()
	case Record:
		 := .(*RecordSchema).Fields()
		 := make(map[string]any, len())
		for ,  := range  {
			[.Name()] = .(.Type())
		}
		return 
	case Ref:
		return .(.(*RefSchema).Schema())
	case Enum:
		 := .(*EnumSchema).Symbols()
		 := int(.ReadInt())
		if  < 0 ||  >= len() {
			.ReportError("Read", "unknown enum symbol")
			return nil
		}
		return []
	case Array:
		 := []any{}
		.ReadArrayCB(func( *Reader) bool {
			 := .(.(*ArraySchema).Items())
			 = append(, )
			return true
		})
		return 
	case Map:
		 := map[string]any{}
		.ReadMapCB(func( *Reader,  string) bool {
			 := .(.(*MapSchema).Values())
			[] = 
			return true
		})
		return 
	case Union:
		 := .(*UnionSchema).Types()
		 := int(.ReadLong())
		if  < 0 ||  > len()-1 {
			.ReportError("Read", "unknown union type")
			return nil
		}
		 = []
		if .Type() == Null {
			return nil
		}

		 := schemaTypeName()
		 := map[string]any{}
		[] = .([])
		return 
	case Fixed:
		 := .(*FixedSchema).Size()
		 := make([]byte, )
		.Read()
		if  != nil && .Type() == Decimal {
			 := .(*DecimalLogicalSchema)
			return ratFromBytes(, .Scale())
		}
		return byteSliceToArray(, )
	default:
		.ReportError("Read", fmt.Sprintf("unexpected schema type: %v", .Type()))
		return nil
	}
}

// ReadArrayCB reads an array with a callback per item.
func ( *Reader) ( func(*Reader) bool) {
	for {
		,  := .ReadBlockHeader()
		if  == 0 {
			break
		}
		for range  {
			()
		}
	}
}

// ReadMapCB reads an array with a callback per item.
func ( *Reader) ( func(*Reader, string) bool) {
	for {
		,  := .ReadBlockHeader()
		if  == 0 {
			break
		}

		for range  {
			 := .ReadString()
			(, )
		}
	}
}

var byteType = reflect.TypeOf((*byte)(nil)).Elem()

func byteSliceToArray( []byte,  int) any {
	 := reflect.New(reflect.ArrayOf(, byteType)).Elem()
	reflect.Copy(, reflect.ValueOf())
	return .Interface()
}