package main

import (
	
	
	
	
	

	
	
	

	
	
	amhelp 
	am 
	arpc 
	ssrpc 
)

var ss = states.DaemonStates

type Args struct {
	Addr  string `default:"localhost:8090"`
	Debug bool   `default:"true" help:"Enable debugging for asyncmachine"`
}

type daemon struct {
	Mach *am.Machine
	Args *Args
	S    *arpc.Server
}

var args Args

func main() {
	 := arg.MustParse(&args)
	 := context.Background()
	,  := newDaemon(, &args)
	if  != nil {
		.Fail(.Error())
	}

	<-.Mach.WhenQueue(.Mach.Add1(ss.Start, nil))
	<-.Mach.WhenNot1(ss.Start, nil)
}

// newDaemon creates a new CLI with a state machine.
func newDaemon( context.Context,  *Args) (*daemon, error) {
	if .Debug {
		fmt.Printf("debugging enabled\n")
		// load .env
		_ = godotenv.Load()
	}

	// init daemon
	 := &daemon{
		Args: ,
	}
	,  := am.NewCommon(, "daemon", states.DaemonSchema, ss.Names(),
		, nil, &am.Opts{
			DontPanicToException: .Debug,
			LogLevel:             am.LogChanges,
			LogArgs:              types.LogArgs,
		})
	if  != nil {
		return nil, 
	}
	if .Debug {
		amhelp.MachDebugEnv()
	}
	.Mach = 

	// init aRPC server
	,  := arpc.NewServer(, .Addr, .Mach.Id(), .Mach, nil)
	if  != nil {
		return nil, 
	}
	if .Debug {
		amhelp.MachDebugEnv(.Mach)
	}
	.S = 
	.Start()
	if  != nil {
		return nil, 
	}
	// TODO print when ready
	fmt.Printf("listening on %s\n", .Addr)

	// REPL on port+1
	, ,  := net.SplitHostPort(.Addr)
	,  := strconv.Atoi()
	 :=  + ":" + strconv.Itoa(+1)
	 = arpc.MachRepl(, , &arpc.ReplOpts{
		AddrDir:    ".",
		ArgsPrefix: types.APrefix,
		Args:       &types.ARpc{},
	})
	if  != nil {
		return nil, 
	}
	// TODO print when ready
	fmt.Printf("REPL listening on %s\n", )

	return , nil
}

func ( *daemon) ( *am.Event) {
	.hOp()
}
func ( *daemon) ( *am.Event) {
	.hOp()
}

// hOp is a sub-handler for common operation logic.
func ( *daemon) ( *am.Event) {
	 := .Mach.NewStateCtx(ss.Start)
	 := .S.Mach.NewStateCtx(ssrpc.ServerStates.ClientConnected)
	,  := onecontext.Merge(, )
	 := types.ParseArgs(.Args).Duration
	 := .Transition().CalledStates()

	fmt.Printf("starting op %s for %s\n", , )
	go func() {
		defer .Mach.Remove(, nil)
		select {
		case <-.Done():
			fmt.Printf("ctx done\n")
			return
		case <-time.After():
		}

		fmt.Printf("op done\n")
		// TODO
		.Mach.AddErr(.S.SendPayload(, , &arpc.MsgSrvPayload{
			Name: "opdone",
			Data: fmt.Sprintf("done for %s", ),
		}), nil)
	}()
}