package wand

import (
	"code.squareroundforest.org/arpio/notation"
	"fmt"
	"io"
	"reflect"
)

func fprintOne(out io.Writer, v any) error {
	if reader, ok := v.(io.Reader); ok {
		_, err := io.Copy(out, reader)
		return err
	}

	if _, ok := v.(fmt.Stringer); ok {
		_, err := fmt.Fprintln(out, v)
		return err
	}

	r := reflect.ValueOf(v)
	switch r.Kind() {
	case reflect.Invalid:
		return nil
	case reflect.Bool,
		reflect.Int,
		reflect.Int8,
		reflect.Int16,
		reflect.Int32,
		reflect.Int64,
		reflect.Uint,
		reflect.Uint8,
		reflect.Uint16,
		reflect.Uint32,
		reflect.Uint64,
		reflect.Uintptr,
		reflect.Float32,
		reflect.Float64,
		reflect.String:
		_, err := fmt.Fprintln(out, v)
		return err
	case reflect.Slice:
		for i := 0; i < r.Len(); i++ {
			if err := fprintOne(out, r.Index(i).Interface()); err != nil {
				return err
			}
		}

		return nil
	case reflect.Pointer:
		return fprintOne(out, r.Elem().Interface())
	default:
		_, err := notation.Fprintlnwt(out, v)
		return err
	}
}

func printOutput(out io.Writer, o []any) error {
	for _, oi := range o {
		if err := fprintOne(out, oi); err != nil {
			return fmt.Errorf("error displaying output: %w", err)
		}
	}

	return nil
}
