package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"time"

	"git.sandpoints.org/Drawwell/SandpointsGitHook/giq"
)

var (
	version  = "21.04.01"
	logLines = ""
)

func check(e error) {
	if e != nil {
		logLines += fmt.Sprintf("\nGit hook version: %s\n~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n", version)
		fmt.Println(logLines)
		log.Fatal(e)
		panic(e)
	}
}

type Hugo struct {
	CatalogName    string
	CatalogPrefix  string
	SourceDir      string
	DestinationDir string
	PublicHTMLName string
}

type Hook struct {
	Context        string
	Publish        bool
	Offline        bool
	Gogit          bool
	Stdinput       string
	ExecutablePath string
	PublicHTMLPath string
}

func gitExePath(hook *Hook) string {
	gexe := "git"
	if runtime.GOOS == "windows" {
		gexe = "git.exe"
	}
	gpath, err := exec.LookPath(gexe)
	check(err)
	if gpath != "" {
		hook.Gogit = false
		return gpath
	} else {
		hook.Gogit = true
		return ""
	}
}

func main() {
	startTime := time.Now()
	logLines := fmt.Sprintf("~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\nSANDPOINTS GITHOOK (%s)\n\n", version)

	// init global struct/variables
	var hook *Hook
	var hugo *Hugo
	var git giq.Git
	var giqi giq.Giqi

	hook = new(Hook)
	hugo = new(Hugo)

	hook.Publish = false
	hook.Gogit = true
	hook.PublicHTMLPath = filepath.Join("/var", "www", "html", "sandpoints")

	hookExe, err := os.Executable()
	check(err)
	hook.ExecutablePath = filepath.Dir(hookExe)
	// hook.ExecutablePath = "/home/m/Downloads/SimpleSandpoints/.git/hooks"
	// hook.ExecutablePath = "/home/m/gitea-repositories/sandpoints/dev.git/hooks/post-receive.d"
	// hook.ExecutablePath = "/home/m/gitea-repositories/sandpoints/simplesandpoints.git/hooks/post-receive.d"
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Scan()
	scannerTxt := scanner.Text()
	hookContext(hook, scannerTxt)
	gitPath := gitExePath(hook)
	giqi = &giq.Gogit{}
	// enforce go-git if mocking hook.ExecutablePath
	// if hook.Gogit {
	// DEFAULT but enforce sysgit if mocking hook.ExecutablePath
	if !hook.Gogit {
		giqi = &giq.Sysgit{}
	}
	git = giqi.GitStruct(hook.ExecutablePath, hook.Context, hook.Stdinput, gitPath)
	hook.Publish = git.Publish
	hugo.SourceDir = git.RepoPath

	if git.IsBare {
		giqi.AddBareWorktree(git.RepoPath, git.IndexPath, git.Worktree, gitPath)
		defer giqi.RemoveBareWorktree(git.RepoPath, git.IndexPath, git.Worktree, gitPath)
		hugo.SourceDir = git.TmpRepoPath
	}

	hugoContext(hugo, git.RepoPath)

	logs := hugoRender(hugo, hook.Offline)
	logLines += fmt.Sprintf(logs)
	if git.IsBare {
		cleanUpPublicHTML(hugo, hook)
		copyToPublicHTML(hugo, hook)

		logLines += fmt.Sprintln("~~~~~~~~~~~~~~~~~~~~~~~~~~~")
		if hook.Publish {
			logLines += fmt.Sprintf("Web site path:\n%s", filepath.Join(hook.PublicHTMLPath, hugo.PublicHTMLName))
		} else {
			logLines += fmt.Sprintf("Web site path:\n%s", filepath.Join(hook.PublicHTMLPath, hugo.PublicHTMLName, "_preview"))
		}
	} else {
		logLines += fmt.Sprintf("Web site path:\n%s", hugo.DestinationDir)
	}

	durationMillseconds := int64(time.Since(startTime) / time.Millisecond)
	logLines = logLines + fmt.Sprintf("\n~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\nTotal githook time: %d ms\n~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n", durationMillseconds)
	logLines = logLines + startTime.Format(time.RFC822) + "\n~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~\n"

	// logLines = logLines + "\n####################################\n"
	// logLines = logLines + fmt.Sprintf("%#v", hugo)
	// logLines = logLines + fmt.Sprintf("%#v", hook)

	writeLastCommitLog(logLines, git.IsBare, hugo, hook)
	fmt.Println(logLines)
}
