package bob

import (
	"context"
	"errors"

	"github.com/benchkram/errz"

	"github.com/benchkram/bob/bob/bobfile"
	"github.com/benchkram/bob/bob/playbook"
)

var (
	ErrNoRebuildRequired = errors.New("no rebuild required")
)

// Build a task and it's dependencies.
func (b *B) Build(ctx context.Context, taskName string) (err error) {
	defer errz.Recover(&err)

	ag, err := b.Aggregate()
	errz.Fatal(err)

	b.PrintVersionCompatibility(ag)

	err = b.nix.BuildNixDependenciesInPipeline(ag, taskName)
	errz.Fatal(err)

	// Hint: Hash computation (playbook execution) can only start after
	// nix dependencies are resolved.
	// Nix dependencies are considered in the input hash of a task.
	p, err := ag.Playbook(
		taskName,
		playbook.WithCachingEnabled(b.enableCaching),
		playbook.WithPredictedNumOfTasks(len(ag.BTasks)),
		playbook.WithMaxParallel(b.maxParallel),
		playbook.WithRemoteStore(ag.Remotestore()),
		playbook.WithLocalStore(b.local),
		playbook.WithPushEnabled(b.enablePush),
		playbook.WithPullEnabled(b.enablePull),
	)
	errz.Fatal(err)

	err = p.Build(ctx)
	errz.Fatal(err)

	return nil
}

// AggregateWithNixDeps does aggregation together with evaluating nix dependecies.
// Nic dependencies are altering a tasks input hash.
// Use this function for building `bob inspect` cmds.
func (b *B) AggregateWithNixDeps(taskName string) (aggregate *bobfile.Bobfile, err error) {
	defer errz.Recover(&err)

	ag, err := b.Aggregate()
	errz.Fatal(err)

	err = b.nix.BuildNixDependenciesInPipeline(ag, taskName)
	errz.Fatal(err)

	return ag, nil
}
