package samples

import (
	
	

	
	
	
	
	

	schemapb 
	schemav2pb 
	
)

type Sample struct {
	ExampleType string            `frostdb:"example_type,rle_dict,asc(0)"`
	Labels      map[string]string `frostdb:"labels,rle_dict,asc(1),null_first"`
	Stacktrace  []uuid.UUID       `frostdb:"stacktrace,rle_dict,asc(3),null_first"`
	Timestamp   int64             `frostdb:"timestamp,asc(2)"`
	Value       int64             `frostdb:"value"`
}

type Samples []Sample

func ( Samples) () (arrow.Record, error) {
	 := records.NewBuild[Sample](memory.NewGoAllocator())
	defer .Release()
	 := .Append(...)
	if  != nil {
		return nil, 
	}
	return .NewRecord(), nil
}

func ( Samples) () []string {
	 := []string{}
	 := map[string]struct{}{}

	for ,  := range  {
		for  := range .Labels {
			if ,  := []; ! {
				 = append(, )
				[] = struct{}{}
			}
		}
	}
	sort.Strings()

	return 
}

func ( Sample) ( []string) parquet.Row {
	// The order of these appends is important. Parquet values must be in the
	// order of the schema and the schema orders columns by their names.

	 := len()
	 := len(.Labels)
	 := make([]parquet.Value, 0, +3)

	 = append(, parquet.ValueOf(.ExampleType).Level(0, 0, 0))

	,  := 0, 0
	for  <  {
		if ,  := .Labels[[]];  {
			 = append(, parquet.ValueOf().Level(0, 1, +1))
			++
			++
			if  >=  {
				for ;  < ; ++ {
					 = append(, parquet.ValueOf(nil).Level(0, 0, +1))
				}
				break
			}
		} else {
			 = append(, parquet.ValueOf(nil).Level(0, 0, +1))
			++
		}
	}
	 = append(, parquet.ValueOf(ExtractLocationIDs(.Stacktrace)).Level(0, 0, +1))
	 = append(, parquet.ValueOf(.Timestamp).Level(0, 0, +2))
	 = append(, parquet.ValueOf(.Value).Level(0, 0, +3))

	return 
}

func ( []uuid.UUID) []byte {
	 := make([]byte, len()*16) // UUID are 16 bytes thus multiply by 16
	 := 0
	for  := len() - 1;  >= 0; -- {
		copy([:+16], [][:])
		 += 16
	}
	return 
}

func () *schemapb.Schema {
	return &schemapb.Schema{
		Name: "test",
		Columns: []*schemapb.Column{{
			Name: "example_type",
			StorageLayout: &schemapb.StorageLayout{
				Type:     schemapb.StorageLayout_TYPE_STRING,
				Encoding: schemapb.StorageLayout_ENCODING_RLE_DICTIONARY,
			},
			Dynamic: false,
		}, {
			Name: "labels",
			StorageLayout: &schemapb.StorageLayout{
				Type:     schemapb.StorageLayout_TYPE_STRING,
				Nullable: true,
				Encoding: schemapb.StorageLayout_ENCODING_RLE_DICTIONARY,
			},
			Dynamic: true,
			Prehash: true,
		}, {
			Name: "stacktrace",
			StorageLayout: &schemapb.StorageLayout{
				Type:     schemapb.StorageLayout_TYPE_STRING,
				Encoding: schemapb.StorageLayout_ENCODING_RLE_DICTIONARY,
			},
			Dynamic: false,
			Prehash: true,
		}, {
			Name: "timestamp",
			StorageLayout: &schemapb.StorageLayout{
				Type: schemapb.StorageLayout_TYPE_INT64,
			},
			Dynamic: false,
		}, {
			Name: "value",
			StorageLayout: &schemapb.StorageLayout{
				Type: schemapb.StorageLayout_TYPE_INT64,
			},
			Dynamic: false,
		}},
		SortingColumns: []*schemapb.SortingColumn{{
			Name:      "example_type",
			Direction: schemapb.SortingColumn_DIRECTION_ASCENDING,
		}, {
			Name:       "labels",
			Direction:  schemapb.SortingColumn_DIRECTION_ASCENDING,
			NullsFirst: true,
		}, {
			Name:      "timestamp",
			Direction: schemapb.SortingColumn_DIRECTION_ASCENDING,
		}, {
			Name:       "stacktrace",
			Direction:  schemapb.SortingColumn_DIRECTION_ASCENDING,
			NullsFirst: true,
		}},
	}
}

func () *schemapb.Schema {
	return &schemapb.Schema{
		Name: "test",
		Columns: []*schemapb.Column{{
			Name: "example_type",
			StorageLayout: &schemapb.StorageLayout{
				Type:     schemapb.StorageLayout_TYPE_STRING,
				Encoding: schemapb.StorageLayout_ENCODING_RLE_DICTIONARY,
			},
			Dynamic: false,
		}, {
			Name: "labels",
			StorageLayout: &schemapb.StorageLayout{
				Type:     schemapb.StorageLayout_TYPE_STRING,
				Nullable: true,
				Encoding: schemapb.StorageLayout_ENCODING_RLE_DICTIONARY,
			},
			Dynamic: true,
		}, {
			Name: "stacktrace",
			StorageLayout: &schemapb.StorageLayout{
				Type:     schemapb.StorageLayout_TYPE_STRING,
				Encoding: schemapb.StorageLayout_ENCODING_RLE_DICTIONARY,
			},
			Dynamic: false,
		}, {
			Name: "timestamp",
			StorageLayout: &schemapb.StorageLayout{
				Type: schemapb.StorageLayout_TYPE_INT64,
			},
			Dynamic: false,
		}, {
			Name: "value",
			StorageLayout: &schemapb.StorageLayout{
				Type: schemapb.StorageLayout_TYPE_INT64,
			},
			Dynamic: false,
		}},
		SortingColumns: []*schemapb.SortingColumn{{
			Name:      "example_type",
			Direction: schemapb.SortingColumn_DIRECTION_ASCENDING,
		}, {
			Name:       "labels",
			Direction:  schemapb.SortingColumn_DIRECTION_ASCENDING,
			NullsFirst: true,
		}, {
			Name:      "timestamp",
			Direction: schemapb.SortingColumn_DIRECTION_ASCENDING,
		}, {
			Name:       "stacktrace",
			Direction:  schemapb.SortingColumn_DIRECTION_ASCENDING,
			NullsFirst: true,
		}},
	}
}

// Adds a float column to the SampleDefinition to be able to test
// aggregations with float values.
func () *schemapb.Schema {
	 := SampleDefinition()
	.Columns = append(.Columns, &schemapb.Column{
		Name: "floatvalue",
		StorageLayout: &schemapb.StorageLayout{
			Type:     schemapb.StorageLayout_TYPE_DOUBLE,
			Nullable: true,
		},
		Dynamic: false,
	})
	return 
}

func () Samples {
	return Samples{
		{
			ExampleType: "cpu",
			Labels: map[string]string{
				"node": "test3",
			},
			Stacktrace: []uuid.UUID{
				{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1},
				{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2},
			},
			Timestamp: 2,
			Value:     5,
		}, {
			ExampleType: "cpu",
			Labels: map[string]string{
				"namespace": "default",
				"pod":       "test1",
			},
			Stacktrace: []uuid.UUID{
				{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1},
				{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2},
			},
			Timestamp: 2,
			Value:     3,
		}, {
			ExampleType: "cpu",
			Labels: map[string]string{
				"container": "test2",
				"namespace": "default",
			},
			Stacktrace: []uuid.UUID{
				{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1},
				{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2},
			},
			Timestamp: 2,
			Value:     3,
		},
	}
}

func ( int) Samples {
	 := Samples{}
	for  := 0;  < ; ++ {
		 = append(,
			Sample{
				ExampleType: "cpu",
				Labels: map[string]string{
					"node": "test3",
				},
				Stacktrace: []uuid.UUID{
					{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1},
					{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2},
				},
				Timestamp: int64(),
				Value:     int64(),
			})
	}
	return 
}

func ( string,  *schemav2pb.StorageLayout) *schemav2pb.Node_Group {
	return &schemav2pb.Node_Group{
		Group: &schemav2pb.Group{
			Name: ,
			Nodes: []*schemav2pb.Node{ // NOTE that this nested group structure for a list is for backwards compatability: https://github.com/apache/parquet-format/blob/master/LogicalTypes.md#lists
				{
					Type: &schemav2pb.Node_Group{
						Group: &schemav2pb.Group{
							Name:     "list",
							Repeated: true,
							Nodes: []*schemav2pb.Node{
								{
									Type: &schemav2pb.Node_Leaf{
										Leaf: &schemav2pb.Leaf{
											Name:          "element",
											StorageLayout: ,
										},
									},
								},
							},
						},
					},
				},
			},
		},
	}
}

func ( string) *schemav2pb.Node {
	return &schemav2pb.Node{
		Type: &schemav2pb.Node_Group{
			Group: &schemav2pb.Group{
				Name: "labels",
				Nodes: []*schemav2pb.Node{
					{
						Type: &schemav2pb.Node_Leaf{
							Leaf: &schemav2pb.Leaf{
								Name: ,
								StorageLayout: &schemav2pb.StorageLayout{
									Type:     schemav2pb.StorageLayout_TYPE_STRING,
									Nullable: true,
									Encoding: schemav2pb.StorageLayout_ENCODING_RLE_DICTIONARY,
								},
							},
						},
					},
				},
			},
		},
	}
}

func ( testing.TB) proto.Message {
	.Helper()
	return &schemav2pb.Schema{
		Root: &schemav2pb.Group{
			Name: "nested",
			Nodes: []*schemav2pb.Node{
				{
					Type: &schemav2pb.Node_Group{
						Group: &schemav2pb.Group{
							Name:  "labels",
							Nodes: []*schemav2pb.Node{},
						},
					},
				},
				{
					Type: NestedListDef("timestamps", &schemav2pb.StorageLayout{
						Type:     schemav2pb.StorageLayout_TYPE_INT64,
						Nullable: true,
						Encoding: schemav2pb.StorageLayout_ENCODING_RLE_DICTIONARY,
					}),
				},
				{
					Type: NestedListDef("values", &schemav2pb.StorageLayout{
						Type:     schemav2pb.StorageLayout_TYPE_INT64,
						Nullable: true,
						Encoding: schemav2pb.StorageLayout_ENCODING_RLE_DICTIONARY,
					}),
				},
			},
		},
		SortingColumns: []*schemav2pb.SortingColumn{
			{
				Path:       "labels",
				Direction:  schemav2pb.SortingColumn_DIRECTION_ASCENDING,
				NullsFirst: true,
			},
			{
				Path:      "timestamp",
				Direction: schemav2pb.SortingColumn_DIRECTION_ASCENDING,
			},
		},
	}
}