package main

import (
	"context"
	"fmt"
	"time"
)

type Mailbox[T0, T1 any] struct {
	ctx    context.Context
	inbox  chan T0
	outbox chan T1
}

// Functions for external use
func (m Mailbox[T0, T1]) Send(v T0) {
	m.inbox <- v
}

func (m Mailbox[T0, T1]) Recv() T1 {
	return <-m.outbox
}

// Functions for mailbox owner
func (m Mailbox[T0, T1]) Read() T0 {
	return <-m.inbox
}

func (m Mailbox[T0, T1]) Write(v T1) {
	m.outbox <- v
}

// Mostly here for example; you may not want buffered channels
func New[T0, T1 any](ctx context.Context, input T0, output T1) mailbox[T0, T1] {
	var m mailbox[T0, T1]
	m.ctx = ctx
	m.inbox = make(chan T0, 32)
	m.outbox = make(chan T1, 32)
	return m
}

func Echo() Mailbox[string, struct{}] {
	m := New(nil, "", struct{}{})
	go func() {
		for {
			v := m.Read() 
			m.Write(v)
		}
	}()
	return m

}

func main() {
	echo := Echo()
	echo.Send("Hello")
	fmt.Println(echo.Recv())
}