package dynparquet

import (
	

	
)

type DynamicRows struct {
	Rows           []parquet.Row
	Schema         *parquet.Schema
	DynamicColumns map[string][]string
	fields         []parquet.Field
}

func (
	 []parquet.Row,  *parquet.Schema,  map[string][]string,  []parquet.Field,
) *DynamicRows {
	return &DynamicRows{
		Schema:         ,
		DynamicColumns: ,
		Rows:           ,
		fields:         ,
	}
}

func ( *DynamicRows) ( int) *DynamicRow {
	return &DynamicRow{
		Schema:         .Schema,
		DynamicColumns: .DynamicColumns,
		Row:            .Rows[],
		fields:         .fields,
	}
}

func ( *DynamicRows) ( int) *DynamicRow {
	 := make(parquet.Row, len(.Rows[]))
	for ,  := range .Rows[] {
		[] = .Clone()
	}

	return &DynamicRow{
		Schema:         .Schema,
		DynamicColumns: .DynamicColumns,
		Row:            ,
		fields:         .fields,
	}
}

func ( *DynamicRows) ( *Schema) bool {
	for  := 1;  < len(.Rows); ++ {
		if .RowLessThan(.Get(), .Get(-1)) {
			return false
		}
	}
	return true
}

func ( parquet.Row,  *parquet.Schema,  map[string][]string,  []parquet.Field) *DynamicRow {
	return &DynamicRow{
		Row:            ,
		Schema:         ,
		DynamicColumns: ,
		fields:         ,
	}
}

type DynamicRow struct {
	Row            parquet.Row
	Schema         *parquet.Schema
	DynamicColumns map[string][]string
	fields         []parquet.Field
}

func ( *Schema) (,  *DynamicRow) bool {
	return .Cmp(, ) < 0
}

func ( *Schema) (,  *DynamicRow) int {
	 := MergeDynamicColumnSets([]map[string][]string{.DynamicColumns, .DynamicColumns})
	 := .ParquetSortingColumns()
	,  := .GetParquetSortingSchema()
	if  != nil {
		panic(fmt.Sprintf("unexpected schema state: %v", ))
	}
	 := .Schema
	defer .PutPooledParquetSchema()

	// Iterate over all the schema columns to prepare the rows for comparison.
	// The main reason we can't directly pass in {a,b}.Row is that they might
	// not have explicit values for dynamic columns we want to compare. These
	// columns need to be populated with a NULL value.
	// Additionally, parquet imposes its column indexes when creating the
	// sorting schema, so these need to be respected.
	 := .Columns()
	 := make(parquet.Row, 0, len())
	 := make(parquet.Row, 0, len())
	for ,  := range  {
		 := [0] // Currently we only support flat schemas.

		 := FindChildIndex(.fields, )
		 := FindChildIndex(.fields, )

		if  == -1 &&  == -1 {
			continue
		}

		,  := extractValues(, , , )
		 = append(, ...)
		 = append(, ...)
	}

	// Set the column indexes according to the merged schema.
	for  := range  {
		[] = [].Level([].RepetitionLevel(), [].DefinitionLevel(), )
		[] = [].Level([].RepetitionLevel(), [].DefinitionLevel(), )
	}

	return .Comparator(...)(, )
}

type DynamicRowSorter struct {
	schema *Schema
	rows   *DynamicRows
}

func ( *Schema,  *DynamicRows) *DynamicRowSorter {
	return &DynamicRowSorter{
		schema: ,
		rows:   ,
	}
}

func ( *DynamicRowSorter) () int {
	return len(.rows.Rows)
}

func ( *DynamicRowSorter) (,  int) bool {
	return .schema.RowLessThan(.rows.Get(), .rows.Get())
}

func ( *DynamicRowSorter) (,  int) {
	.rows.Rows[], .rows.Rows[] = .rows.Rows[], .rows.Rows[]
}

func extractValues(,  *DynamicRow, ,  int) ([]parquet.Value, []parquet.Value) {
	if  != -1 &&  == -1 {
		return ValuesForIndex(.Row, ), []parquet.Value{parquet.ValueOf(nil).Level(0, 0, )}
	}

	if  == -1 &&  != -1 {
		return []parquet.Value{parquet.ValueOf(nil).Level(0, 0, )}, ValuesForIndex(.Row, )
	}

	return ValuesForIndex(.Row, ), ValuesForIndex(.Row, )
}

func ( []parquet.Field,  string) int {
	for ,  := range  {
		if .Name() ==  {
			return 
		}
	}
	return -1
}

func ( parquet.Row,  int) []parquet.Value {
	 := -1
	 := -1
	for ,  := range  {
		 := .Column()
		if  != -1 &&  == -1 {
			return [:]
		}
		if  ==  {
			if  == -1 {
				 = 
			}
			 =  + 1
		}
	}

	return [:]
}