package parts

import (
	
	

	

	
)

type Part interface {
	// Record returns the Arrow record for the part. If the part is not an Arrow
	// record part, nil is returned.
	Record() arrow.Record
	Release()
	Retain()
	SerializeBuffer(schema *dynparquet.Schema, w dynparquet.ParquetWriter) error
	AsSerializedBuffer(schema *dynparquet.Schema) (*dynparquet.SerializedBuffer, error)
	NumRows() int64
	Size() int64
	CompactionLevel() int
	TX() uint64
	Least() (*dynparquet.DynamicRow, error)
	Most() (*dynparquet.DynamicRow, error)
	OverlapsWith(schema *dynparquet.Schema, otherPart Part) (bool, error)
	Write(io.Writer) error
}

type basePart struct {
	tx              uint64
	compactionLevel int
	minRow          *dynparquet.DynamicRow
	maxRow          *dynparquet.DynamicRow
	release         func()
}

func ( *basePart) () int {
	return .compactionLevel
}

func ( *basePart) () uint64 { return .tx }

type Option func(*basePart)

func ( int) Option {
	return func( *basePart) {
		.compactionLevel = 
	}
}

func ( func()) Option {
	return func( *basePart) {
		.release = 
	}
}

type PartSorter struct {
	schema *dynparquet.Schema
	parts  []Part
	err    error
}

func ( *dynparquet.Schema,  []Part) *PartSorter {
	return &PartSorter{
		schema: ,
		parts:  ,
	}
}

func ( *PartSorter) () int {
	return len(.parts)
}

func ( *PartSorter) (,  int) bool {
	,  := .parts[].Least()
	if  != nil {
		.err = 
		return false
	}
	,  := .parts[].Least()
	if  != nil {
		.err = 
		return false
	}
	return .schema.RowLessThan(, )
}

func ( *PartSorter) (,  int) {
	.parts[], .parts[] = .parts[], .parts[]
}

func ( *PartSorter) () error {
	return .err
}

// FindMaximumNonOverlappingSet removes the minimum number of parts from the
// given slice in order to return the maximum non-overlapping set of parts.
// The function returns the non-overlapping parts first and any overlapping
// parts second. The parts returned are in sorted order according to their Least
// row.
func ( *dynparquet.Schema,  []Part) ([]Part, []Part, error) {
	if len() < 2 {
		return , nil, nil
	}
	 := NewPartSorter(, )
	sort.Sort()
	if .Err() != nil {
		return nil, nil, .Err()
	}

	// Parts are now sorted according to their Least row.
	 := 0
	,  := [0].Most()
	if  != nil {
		return nil, nil, 
	}
	 := make([]Part, 0, len())
	 := make([]Part, 0, len())
	var  Part
	for  := 1;  < len(); ++ {
		,  := [].Least()
		if  != nil {
			return nil, nil, 
		}
		,  := [].Most()
		if  != nil {
			return nil, nil, 
		}
		if .Cmp(, ) <= 0 {
			// No overlap, append the previous part and update end for the next
			// iteration.
			 = append(, [])
			 = 
			 = 
			continue
		}

		// This part overlaps with the previous part. Remove the part with
		// the highest end row.
		if .Cmp(, ) >= 0 {
			 = append(, [])
			 = 
			 = 
		} else {
			// The current part must be removed. Don't update prevEnd or prev,
			// this will be used in the next iteration and must stay the same.
			 = append(, [])

			if  == len()-1 { // This is the last iteration mark this one as missing
				 = []
			}
		}
	}
	if len() == 0 || [len()-1] != [len()-1] {
		// The last part either did not overlap with its previous part, or
		// overlapped but had a smaller end row than its previous part (so the
		// previous part is in the overlapping slice). The last part must be
		// appended to nonOverlapping.
		 = append(, [len()-1])
	} else if  != nil {
		 = append(, )
	}
	return , , nil
}