package muesli

import (
	"fmt"
	"testing"
)

func TestVm1(test *testing.T) {
	vm := NewVM()
	bi := vm.RegisterBuiltin("foo", func(vm *VM, args ...Value) []Value {
		fmt.Printf("I am foo. See me foo?")
		return []Value{}
	})

	if vm == nil {
		test.Errorf("Could not construct VM")
	}

	if _, ok := bi.(*BuiltinValue); !ok {
		test.Errorf("Could not construct register a builtin function.")
	}

	foo := vm.Lookup("foo")
	biv, ok := foo.(*BuiltinValue)
	if foo == nil || !ok {
		test.Errorf("Could not look up foo.")
	}

	biv.Handler(vm)

}

func ExampleVm1() {
	vm := NewVM()
	vm.RegisterBuiltin("foo", func(vm *VM, args ...Value) []Value {
		fmt.Printf("I am foo. See me foo?")
		return []Value{}
	})

	foo := vm.Lookup("foo")
	biv, ok := foo.(*BuiltinValue)
	if foo == nil || !ok {
		fmt.Println("Could not look up foo.")
	}

	//Output: I am foo. See me foo?
	biv.Handler(vm)

}

func ExampleVm2() {
	vm := NewVM()
	vm.RegisterBuiltin("foo", func(vm *VM, args ...Value) []Value {
		var s string
		From(args[0], &s)
		fmt.Printf("I am foo. See me %s?", s)
		return []Value{}
	})

	//Output: I am foo. See me bar?
	vm.CallNamed("foo", To("bar"))

}

func ExampleVm3() {
	vm := NewVM()
	vm.RegisterBuiltin("multi", func(vm *VM, args ...Value) []Value {
		var one string
		var two int64
		err := ListFrom(args, &one, &two)
		if err != nil {
			fmt.Printf("Error: %s", err.Error())
		}
		fmt.Printf("I am multi. See me %s, %d?", one, two)
		return []Value{}
	})

	//Output: I am multi. See me bar, 7?
	vm.CallNamed("multi", ListTo("bar", 7)...)

}

func ExampleVm4() {
	vm := NewVM()
	vm.RegisterBuiltin("printf", func(vm *VM, args ...Value) []Value {
		var form string
		var rest = args[1:len(args)]
		resri := ListFromList(rest)
		err := From(args[0], &form)
		if err != nil {
			fmt.Printf("Error: %s", err.Error())
		} else {
			fmt.Printf(form, resri...)
		}
		return []Value{}
	})

	//Output: printf 7
	vm.CallNamed("printf", ListTo("printf %d", 7)...)

}