package main

import (
	"fmt"
	"sync"
	"time"
)

type PizzaTool chan struct{}

type PizzaMaker struct {
	id                            int
	leftPizzaTool, rightPizzaTool PizzaTool
}

var wg sync.WaitGroup

func (p PizzaMaker) makePizza() {
	defer wg.Done()

	for j := 0; j < 3; j++ {
		<-p.leftPizzaTool
		<-p.rightPizzaTool

		p.complain("preparing pizza")
		time.Sleep(time.Second)

		p.rightPizzaTool <- struct{}{}
		p.leftPizzaTool <- struct{}{}

		p.complain("finished preparing pizza")
		time.Sleep(time.Second)
	}
}

func (p PizzaMaker) complain(action string) {
	fmt.Printf("PizzaMaker %d is %v\n", p.id, action)
}

func main() {
	count := 5

	pizzaTools := make([]PizzaTool, count)
	for i := 0; i < count; i++ {
		pizzaTools[i] = make(PizzaTool, 1)
		pizzaTools[i] <- struct{}{}
	}

	pizzaMakers := make([]*PizzaMaker, count)
	for i := 0; i < count; i++ {
		pizzaMakers[i] = &PizzaMaker{
			id:             i,
			leftPizzaTool:  pizzaTools[i],
			rightPizzaTool: pizzaTools[(i+1)%count],
		}

		wg.Add(1)
		go pizzaMakers[i].makePizza()
	}

	wg.Wait()
}
