package testpkg

import (
	"fmt"
	"sync"
)

func NewT() func() {
	return func() {}
}

func Fn(_ int) {}

type Worker struct{}

func (Worker) SetLimit(int) {}
func (Worker) Run()         {}

func Go() {
	fooFunc := func() {}
	go fooFunc()

	barFunc := func() {}
	go fooFunc() // want `missing whitespace above this line \(no shared variables above go\)`

	_ = barFunc

	go func() {
		fmt.Println("hey")
	}()

	cuddled := true
	go func() { // want `missing whitespace above this line \(no shared variables above go\)`
		fmt.Println("hey")
	}()

	_ = cuddled

	argToGo := 1
	go Fn(argToGo)

	notArgToGo := 1
	go Fn(argToGo) // want `missing whitespace above this line \(no shared variables above go\)`

	_ = notArgToGo

	t1 := NewT()
	t2 := NewT()
	t3 := NewT()

	go t1()
	go t2()
	go t3()

	multiCuddle1 := NewT()
	multiCuddle2 := NewT() // want `missing whitespace above this line \(too many statements above go\)`
	go multiCuddle2()

	t4 := NewT()
	t5 := NewT() // want `missing whitespace above this line \(too many statements above go\)`
	go t5()
	go t4()

	_, _, _, _, _, _, _ = t1, t2, t3, t4, t5, multiCuddle1, multiCuddle2
}

func GoFuncLit() {
	// Cuddling allowed: variable is used inside the anonymous function body.
	sharedVar := 1
	go func() {
		fmt.Println(sharedVar)
	}()

	// Cuddling not allowed: variable is not used inside the anonymous function body.
	notShared := 1
	go func() { // want `missing whitespace above this line \(no shared variables above go\)`
		fmt.Println("not using notShared")
	}()

	_ = notShared
}

func GoExprStmt() {
	var wg sync.WaitGroup

	wg.Add(1)
	go func() {
		defer wg.Done()
	}()

	wg.Wait()
}

func GoExprStmtDirectCall() {
	t := Worker{}

	t.SetLimit(1)
	go t.Run()
}

func GoExprStmtNoShared() {
	var wg sync.WaitGroup

	fmt.Println("unrelated")
	go func() { // want `missing whitespace above this line \(no shared variables above go\)`
		defer wg.Done()
	}()

	wg.Wait()
}
