package cluster

import "sort"

var (
	_ MachineIterator = Machines(nil)
	_ sort.Interface  = Machines(nil)
)

// A MachineIterator is a set of Machines we can iterate on
type MachineIterator interface {
	ForEachMachine(func(*Machine) bool)
}

// Machines is a list of Machine objects
type Machines []*Machine

// ForEachMachine calls a function for each Machine in the list
// until instructed to terminate the loop
func (m Machines) ForEachMachine(fn func(*Machine) bool) {
	for _, p := range m {
		if fn(p) {
			return
		}
	}
}

// Len returns the number of machines in the list
func (m Machines) Len() int {
	return len(m)
}

// Less implements sort.Interface to sort the list
func (m Machines) Less(i, j int) bool {
	a, b := m[i], m[j]
	za, zb := a.Zone(), b.Zone()

	switch {
	case za == zb:
		return a.ID < b.ID
	default:
		return za < zb
	}
}

// Swap implements sort.Interface to sort the list
func (m Machines) Swap(i, j int) {
	m[i], m[j] = m[j], m[i]
}

// FilterMachines produces a subset of the machines offered by the given
// iterator fulfilling a condition
func FilterMachines(m MachineIterator, cond func(*Machine) bool) (Machines, int) {
	var out []*Machine

	if cond == nil {
		// unconditional
		cond = func(*Machine) bool { return true }
	}

	m.ForEachMachine(func(p *Machine) bool {
		if cond(p) {
			out = append(out, p)
		}
		return false
	})

	return out, len(out)
}