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

import (
	
	

	
	format 
)

// Column encapsulates the information necessary to interpret primitive
// column data in the context of a particular schema. We have to examine
// the node structure of a column's path to the root in the schema tree
// to be able to reassemble the nested structure from the repetition and
// definition levels.
type Column struct {
	pnode *PrimitiveNode
	// the maximum definition level in this column
	// if this is > 0 then either this column or a parent column must be optional.
	maxDefLvl int16
	// the maximum repetition level in this column
	// if this is > 0, then either this column or a parent column must be repeated.
	// when the repetition level in the column data equals this value, it indicates
	// additional elements in the innermost list.
	maxRepLvl int16
}

// NewColumn returns a new column object for the given node with the provided
// maximum definition and repetition levels.
func ( *PrimitiveNode, ,  int16) *Column {
	return &Column{, , }
}

// Name is the column's name
func ( *Column) () string { return .pnode.Name() }

// ColumnPath returns the full path to this column from the root of the schema
func ( *Column) () parquet.ColumnPath { return .pnode.columnPath() }

// Path is equivalent to ColumnPath().String() returning the dot-string version of the path
func ( *Column) () string { return .pnode.Path() }

// TypeLength is -1 if not a FixedLenByteArray, otherwise it is the length of elements in the column
func ( *Column) () int { return .pnode.TypeLength() }

func ( *Column) () int16        { return .maxDefLvl }
func ( *Column) () int16        { return .maxRepLvl }
func ( *Column) () parquet.Type       { return .pnode.PhysicalType() }
func ( *Column) () ConvertedType     { return .pnode.convertedType }
func ( *Column) () LogicalType         { return .pnode.logicalType }
func ( *Column) () parquet.ColumnOrder { return .pnode.ColumnOrder }
func ( *Column) () string {
	var  strings.Builder
	.WriteString("column descriptor = {\n")
	fmt.Fprintf(&, "  name: %s,\n", .Name())
	fmt.Fprintf(&, "  path: %s,\n", .Path())
	fmt.Fprintf(&, "  physical_type: %s,\n", .PhysicalType())
	fmt.Fprintf(&, "  converted_type: %s,\n", .ConvertedType())
	fmt.Fprintf(&, "  logical_type: %s,\n", .LogicalType())
	fmt.Fprintf(&, "  max_definition_level: %d,\n", .MaxDefinitionLevel())
	fmt.Fprintf(&, "  max_repetition_level: %d,\n", .MaxRepetitionLevel())
	if .PhysicalType() == parquet.Types.FixedLenByteArray {
		fmt.Fprintf(&, "  length: %d,\n", .TypeLength())
	}
	if .ConvertedType() == ConvertedTypes.Decimal {
		fmt.Fprintf(&, "  precision: %d,\n  scale: %d,\n", .pnode.decimalMetaData.Precision, .pnode.decimalMetaData.Scale)
	}
	.WriteString("}")
	return .String()
}

// Equals will return true if the rhs Column has the same Max Repetition and Definition levels
// along with having the same node definition.
func ( *Column) ( *Column) bool {
	return .pnode.Equals(.pnode) &&
		.MaxRepetitionLevel() == .MaxRepetitionLevel() &&
		.MaxDefinitionLevel() == .MaxDefinitionLevel()
}

// SchemaNode returns the underlying Node in the schema tree for this column.
func ( *Column) () Node {
	return .pnode
}

// SortOrder returns the sort order of this column's statistics based on the
// Logical and Converted types.
func ( *Column) () SortOrder {
	if .LogicalType() != nil {
		return GetLogicalSortOrder(.LogicalType(), format.Type(.pnode.PhysicalType()))
	}
	return GetSortOrder(.ConvertedType(), format.Type(.pnode.PhysicalType()))
}