// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package testexec

import (
	"sort"
)

// Shard represents a set of tests with a common execution environment.
type Shard struct {
	// Name is the identifier for the shard.
	Name string `json:"name"`

	// Tests is the set of test to be executed in this shard.
	Tests []Test `json:"tests"`

	// Env is a generalized notion of the execution environment for the shard.
	Env Environment `json:"environment"`
}

// MakeShards is the core algorithm to this tool. It takes a set of test specs and produces
// a set of shards which may then be converted into Swarming tasks. Test shards with a
// label different from the provided will be ignored.
//
// This is the most naive algorithm at the moment. It just merges all tests together which
// have the same environment setting into the same shard.
func MakeShards(specs []TestSpec, label string) []*Shard {
	// Collect the order of the shards so our shard ordering is deterministic with
	// respect to the input.
	envToSuites := make(map[Environment][]Test)
	envs := []Environment{}
	for _, spec := range specs {
		if spec.Label != label {
			continue
		}
		for _, env := range spec.Envs {
			if _, ok := envToSuites[env]; !ok {
				envs = append(envs, env)
			}
			envToSuites[env] = append(envToSuites[env], spec.Test)
		}
	}
	shards := make([]*Shard, 0, len(envs))
	for _, env := range envs {
		tests := envToSuites[env]
		sort.Slice(tests, func(i, j int) bool {
			return tests[i].Location < tests[j].Location
		})
		shards = append(shards, &Shard{
			Name:  env.Name(),
			Tests: tests,
			Env:   env,
		})
	}
	return shards
}
