package values

import (
	"fmt"
	"os"
	"os/exec"
	"strings"
)

// If an error is encountered while assigning the value to gitRootDirectory, the program is terminated by panic().
// This heavy-handed response is because so much of the program depends on the gitRootDirectory value. If this value is
// missing, there is no reason to proceed. The program simply will not be successful without it.
var gitRootDirectory = func() string {
	gitRootOutput, err := exec.Command("git", "rev-parse", "--show-toplevel").Output()
	if err != nil {
		panic(fmt.Sprintf("Unable to get git root directory: %v", err))
	}
	return strings.Join(strings.Fields(string(gitRootOutput)), "")
}()

// GetGitRootDirectory returns path to the project's root. There is no trailing "/".
// Example: /Users/lovelace/go/eks-distro
func GetGitRootDirectory() string {
	return gitRootDirectory
}

// NewDirectory should not be created directly and instead should only be generated by calling MakeNewDirectory.
type NewDirectory struct {
	ap AbsolutePath
}

// MakeNewDirectory creates a new directory at provided ap. The provided ap cannot be a path to an existing directory.
func MakeNewDirectory(ap AbsolutePath) (*NewDirectory, error) {
	if err := os.Mkdir(ap.String(), 0777); err != nil {
		return nil, fmt.Errorf("creating release docs directory: %w", err)
	}
	return &NewDirectory{ap}, nil
}

// String returns the absolute path value as a string.
func (nd *NewDirectory) String() string {
	return nd.ap.String()
}

// RemoveNewDirectory delete the directory and the associated path value in nd.
func (nd *NewDirectory) RemoveNewDirectory() error {
	if err := os.RemoveAll(nd.String()); err != nil {
		return fmt.Errorf("deleting directory %s: %w", nd.String(), err)
	}
	nd.ap = ""
	return nil
}

// StripRootDirectory returns the absolute filepath with the root directory path removed.
func (nd *NewDirectory) StripRootDirectory() string {
	return nd.ap.StripRootDirectory()
}
