package app

import (
	
	

	
)

// RangeLoop represents a control structure that iterates within a slice, an
// array or a map.
type RangeLoop interface {
	UI

	// Slice sets the loop content by repeating the given function for the
	// number of elements in the source.
	//
	// It panics if the range source is not a slice or an array.
	Slice(f func(int) UI) RangeLoop

	// Map sets the loop content by repeating the given function for the number
	// of elements in the source. Elements are ordered by keys.
	//
	// It panics if the range source is not a map or if map keys are not strings.
	Map(f func(string) UI) RangeLoop

	body() []UI
}

// Range returns a range loop that iterates within the given source. Source must
// be a slice, an array or a map with strings as keys.
func ( any) RangeLoop {
	return rangeLoop{source: }
}

type rangeLoop struct {
	children []UI
	source   any
}

func ( rangeLoop) ( func(int) UI) RangeLoop {
	 := reflect.ValueOf(.source)
	if .Kind() != reflect.Slice && .Kind() != reflect.Array {
		panic(errors.New("range loop source is not a slice or array").
			WithTag("src-type", .Type),
		)
	}

	 := make([]UI, 0, .Len())
	for  := 0;  < .Len(); ++ {
		 = append(, FilterUIElems(())...)
	}

	.children = 
	return 
}

func ( rangeLoop) ( func(string) UI) RangeLoop {
	 := reflect.ValueOf(.source)
	if .Kind() != reflect.Map {
		panic(errors.New("range loop source is not a map").
			WithTag("src-type", .Type),
		)
	}

	if  := .Type().Key(); .Kind() != reflect.String {
		panic(errors.New("range loop source keys are not strings").
			WithTag("src-type", .Type).
			WithTag("key-type", ),
		)
	}

	 := make([]UI, 0, .Len())
	 := make([]string, 0, .Len())

	for ,  := range .MapKeys() {
		 = append(, .String())
	}
	sort.Strings()

	for ,  := range  {
		 = append(, FilterUIElems(())...)
	}

	.children = 
	return 
}

func ( rangeLoop) () Value {
	return nil
}

func ( rangeLoop) () bool {
	return false
}

func ( rangeLoop) (UI) UI {
	return nil
}

func ( rangeLoop) () UI {
	return nil
}

func ( rangeLoop) () []UI {
	return .children
}