// BuildAllProjects ...
func (builder Model) BuildAllProjects(configuration, platform string, prepareCallback PrepareCommandCallback, callback BuildCommandCallback) ([]string, error) {
	warnings := []string{}

	if err := validateSolutionConfig(builder.solution, configuration, platform); err != nil {
		return warnings, err
	}

	buildableProjects, warns := builder.buildableProjects(configuration, platform)
	if len(buildableProjects) == 0 {
		return warns, fmt.Errorf("No project to build found")
	}

	perfomedCommands := []tools.Printable{}

	for _, proj := range buildableProjects {
		buildCommands, warns, err := builder.buildProjectCommand(configuration, platform, proj)
		warnings = append(warnings, warns...)
		if err != nil {
			return warnings, fmt.Errorf("Failed to create build command, error: %s", err)
		}

		for _, buildCommand := range buildCommands {
			// Callback to let the caller to modify the command
			if prepareCallback != nil {
				editabeCommand := tools.Editable(buildCommand)
				prepareCallback(builder.solution.Name, proj.Name, proj.ProjectType, &editabeCommand)
			}

			// Check if same command was already performed
			alreadyPerformed := false
			if tools.PrintableSliceContains(perfomedCommands, buildCommand) {
				alreadyPerformed = true
			}

			// Callback to notify the caller about next running command
			if callback != nil {
				callback(builder.solution.Name, proj.Name, proj.ProjectType, buildCommand.PrintableCommand(), alreadyPerformed)
			}

			if !alreadyPerformed {
				if err := buildCommand.Run(); err != nil {
					return warnings, err
				}
				perfomedCommands = append(perfomedCommands, buildCommand)
			}
		}
	}

	return warnings, nil
}
// BuildAllNunitTestProjects ...
func (builder Model) BuildAllNunitTestProjects(configuration, platform string, prepareCallback PrepareCommandCallback, callback BuildCommandCallback) ([]string, error) {
	warnings := []string{}

	if err := validateSolutionConfig(builder.solution, configuration, platform); err != nil {
		return warnings, err
	}

	buildableProjects, warns := builder.buildableNunitTestProjects(configuration, platform)
	if len(buildableProjects) == 0 {
		return warns, fmt.Errorf("No project to build found")
	}

	nunitConsolePth, err := nunit.SystemNunit3ConsolePath()
	if err != nil {
		return warnings, err
	}

	perfomedCommands := []tools.Printable{}

	//
	// First build solution
	buildCommand, err := builder.buildSolutionCommand(configuration, platform)
	if err != nil {
		return warnings, fmt.Errorf("Failed to create build command, error: %s", err)
	}

	// Callback to let the caller to modify the command
	if prepareCallback != nil {
		editabeCommand := tools.Editable(buildCommand)
		prepareCallback(builder.solution.Name, "", constants.ProjectTypeUnknown, &editabeCommand)
	}

	// Check if same command was already performed
	alreadyPerformed := false
	if tools.PrintableSliceContains(perfomedCommands, buildCommand) {
		alreadyPerformed = true
	}

	// Callback to notify the caller about next running command
	if callback != nil {
		callback(builder.solution.Name, "", constants.ProjectTypeUnknown, buildCommand.PrintableCommand(), alreadyPerformed)
	}

	if !alreadyPerformed {
		if err := buildCommand.Run(); err != nil {
			return warnings, err
		}
		perfomedCommands = append(perfomedCommands, buildCommand)
	}
	// ---

	//
	// Then build all test projects
	for _, testProj := range buildableProjects {
		buildCommand, warns, err := builder.buildNunitTestProjectCommand(configuration, platform, testProj, nunitConsolePth)
		warnings = append(warnings, warns...)
		if err != nil {
			return warnings, fmt.Errorf("Failed to create build command, error: %s", err)
		}

		// Callback to let the caller to modify the command
		if prepareCallback != nil {
			editabeCommand := tools.Editable(buildCommand)
			prepareCallback(builder.solution.Name, testProj.Name, testProj.ProjectType, &editabeCommand)
		}

		// Check if same command was already performed
		alreadyPerformed := false
		if tools.PrintableSliceContains(perfomedCommands, buildCommand) {
			alreadyPerformed = true
		}

		// Callback to notify the caller about next running command
		if callback != nil {
			callback(builder.solution.Name, testProj.Name, testProj.ProjectType, buildCommand.PrintableCommand(), alreadyPerformed)
		}

		if !alreadyPerformed {
			if err := buildCommand.Run(); err != nil {
				return warnings, err
			}
			perfomedCommands = append(perfomedCommands, buildCommand)
		}
	}
	// ---

	return warnings, nil
}