package main

import (
	am 
)

const log = am.LogOps

func init() {
	// am-dbg is required for debugging, go run it
	// import amhelp "github.com/pancsta/asyncmachine-go/pkg/helpers"
	// go run github.com/pancsta/asyncmachine-go/tools/cmd/am-dbg@latest
	// amhelp.EnableDebugging(false)
	// amhelp.SetEnvLogLevel(am.LogOps)
}

func main() {
	FooBar()
	FileProcessed()
	DryWaterWet()
	RemoveByAdd()
	AddOptionalRemoveMandatory()
	Mutex()
	Quiz()
}

func () {
	 := newMach("FooBar", am.Schema{
		"Foo": {Require: am.S{"Bar"}},
		"Bar": {},
	})
	.Add1("Foo", nil)
	// TODO quiz: is Foo active?
}

func () {
	 := newMach("FileProcessed", am.Schema{
		"ProcessingFile": { // async
			Remove: am.S{"FileProcessed"},
		},
		"FileProcessed": { // async
			Remove: am.S{"ProcessingFile"},
		},
		"InProgress": { // sync
			Auto:    true,
			Require: am.S{"ProcessingFile"},
		},
	})
	 := am.NewLastTxTracer()
	 := .BindTracer()
	if  != nil {
		panic()
	}

	.Add1("ProcessingFile", nil)
	// TODO quiz: is InProgress active?
	.Add1("FileProcessed", nil)

	println()
}

func () {
	 := newMach("DryWaterWet", am.Schema{
		"Wet": {
			Require: am.S{"Water"},
		},
		"Dry": {
			Remove: am.S{"Water"},
		},
		"Water": {
			Add:    am.S{"Wet"},
			Remove: am.S{"Dry"},
		},
	})
	.Add1("Dry", nil)
	.Add1("Water", nil)
	.Add1("Dry", nil)
	// TODO quiz: is Wet active?
}

func () {
	 := newMach("RemoveByNonCalled", am.Schema{
		"A": {Add: am.S{"B"}},
		"B": {Remove: am.S{"C"}},
		"C": {},
	})
	.Add1("C", nil)
	.Add1("A", nil)
	// TODO quiz: is C active?
}

func () {
	 := newMach("AddIsOptional", am.Schema{
		"A": {Add: am.S{"B"}},
		"B": {},
		"C": {Remove: am.S{"B"}},
	})
	.Add(am.S{"A", "C"}, nil)
	// TODO quiz: is B active?
}

func () {
	 := newMach("Mutex", am.Schema{
		"A": {Remove: am.S{"A", "B", "C"}},
		"B": {Remove: am.S{"A", "B", "C"}},
		"C": {Remove: am.S{"A", "B", "C"}},
	})
	.Add1("A", nil)
	.Add1("B", nil)
	.Add1("C", nil)
	// TODO quiz: which one is active?
}

func () {
	 := newMach("Quiz", am.Schema{
		"A": {Add: am.S{"B"}},
		"B": {
			Require: am.S{"D"},
			Add:     am.S{"C"},
		},
		"C": {},
		"D": {Remove: am.S{"C"}},
		"E": {Add: am.S{"D"}},
	})
	.Add(am.S{"A", "E"}, nil)
	// TODO quiz: which one is active?
}

// playground helpers

func newMach( string,  am.Schema) *am.Machine {
	 := am.New(nil, , &am.Opts{
		Id:        ,
		DontLogId: true,
		Tracers:   []am.Tracer{&Tracer{}},
		LogLevel:  log,
	})
	println("\n")
	println("-----")
	println("mach: " + .Id())
	println("-----")

	// DEBUG
	// amhelp.MachDebugEnv(mach)

	return 
}

type Tracer struct {
	*am.NoOpTracer
}

func ( *Tracer) ( *am.Transition) {
	// println("=> " + tx.Machine.MutString())
}