// Copyright 2023 wanderer <a_mirre at utb dot cz>
// SPDX-License-Identifier: GPL-3.0-or-later

package ga

import "golang.org/x/exp/rand"

func (p *SOMAT3APopulation) organise() (int, []int) {
	leader := p.selectLeader()
	migrants := p.selectMigrants(leader)

	return leader, migrants
}

func (p *SOMAT3APopulation) selectMigrants(leader int) []int {
	m := make([]int, p.M)
	n := make([]int, p.N)
	popCount := len(p.Population)

	m[0] = rand.Intn(popCount)

	for i := 1; i < p.M; i++ {
	mgen:
		candidateM := rand.Intn(popCount)

		for _, v := range m {
			if candidateM == v {
				goto mgen
			}
		}

		m[i] = candidateM
	}

	n[0] = rand.Intn(p.M)

	for i := 1; i < p.N; i++ {
	ngen:
		candidateN := rand.Intn(p.M)

		for _, v := range n {
			if candidateN == v || candidateN == leader {
				goto ngen
			}
		}

		n[i] = candidateN
	}

	return n
}

func (p *SOMAT3APopulation) selectLeader() int {
	k := make([]int, p.K)
	popCount := len(p.Population)

	k[0] = rand.Intn(popCount)

	for i := 1; i < p.K; i++ {
	kgen:
		candidate := rand.Intn(popCount)

		for _, v := range k {
			if candidate == v {
				goto kgen
			}
		}

		k[i] = candidate
	}

	// choose one of K to become the leader.
	leader := k[rand.Intn(p.K)]

	return leader
}
