// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.

// operand-list.go
package expr

import (
	"fmt"
	"strings"
)

type ListType []any

func (ls *ListType) ToString(opt FmtOpt) string {
	var sb strings.Builder
	sb.WriteByte('[')
	if len(*ls) > 0 {
		if opt&MultiLine != 0 {
			sb.WriteString("\n  ")
		}
		for i, item := range []any(*ls) {
			if i > 0 {
				if opt&MultiLine != 0 {
					sb.WriteString(",\n  ")
				} else {
					sb.WriteString(", ")
				}
			}
			if s, ok := item.(string); ok {
				sb.WriteByte('"')
				sb.WriteString(s)
				sb.WriteByte('"')
			} else {
				sb.WriteString(fmt.Sprintf("%v", item))
			}
		}
		if opt&MultiLine != 0 {
			sb.WriteByte('\n')
		}
	}
	sb.WriteByte(']')
	return sb.String()
}

func (ls *ListType) String() string {
	return ls.ToString(0)
}

func newListA(listAny ...any) (list *ListType) {
	return newList(listAny)
}

func newList(listAny []any) (list *ListType) {
	if listAny != nil {
		ls := make(ListType, len(listAny))
		for i, item := range listAny {
			ls[i] = item
		}
		list = &ls
	}
	return
}


// -------- list term
func newListTermA(args ...*term) *term {
	return newListTerm(args)
}

func newListTerm(args []*term) *term {
	return &term{
		tk:       *NewValueToken(0, 0, SymList, "[]", args),
		parent:   nil,
		children: nil,
		position: posLeaf,
		priority: priValue,
		evalFunc: evalList,
	}
}

// -------- list func
func evalList(ctx ExprContext, self *term) (v any, err error) {
	list, _ := self.value().([]*term)
	items := make(ListType, len(list))
	for i, tree := range list {
		var param any
		if param, err = tree.compute(ctx); err != nil {
			break
		}
		items[i] = param
	}
	if err == nil {
		v = &items
	}
	return
}