package sync

import (
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"time"

	"git.csclub.uwaterloo.ca/public/merlin/config"
)

func postRepoSync(repo *config.Repo, exit int) {
	if repo.DryRun {
		repo.Logger.Debug("post sync not run because in dry run mode")
		return
	}

	switch exit {
	case config.SUCCESS:
		go zfsSync(repo)
		go postSyncTraceUpdate(repo)
		return

	case config.FAILURE:
		go backupRsyncFailLog(repo)
		return
	}
}

func zfsSync(repo *config.Repo) {
	// we are not using zfs snapshots at the moment
	repo.Logger.Debug("Would run a zfssync if not disabled")
	return

	out, err := exec.Command("/bin/sh", "/home/mirror/bin/zfssync", repo.Name).CombinedOutput()
	if err != nil {
		repo.Logger.Error(err)
	} else {
		f, err := os.OpenFile(repo.ZfssyncLogFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
		if err != nil {
			repo.Logger.Error(err.Error())
		} else {
			f.Write(out)
		}
	}
}

// updates a trace file after the repo has finished syncing
func postSyncTraceUpdate(repo *config.Repo) {
	switch repo.SyncType {
	case "csc-sync-debian":
		cscPostDebian(repo)
	}
}

// update our trace file's modification date by writing the current time
func cscPostDebian(repo *config.Repo) {
	targetDir := filepath.Join(buildDownloadDir(repo), "project/trace")
	target := filepath.Join(targetDir, config.Conf.Hostname)

	os.MkdirAll(targetDir, 0755)
	f, err := os.OpenFile(target, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)

	if err != nil {
		repo.Logger.Error("Unable to open trace file: " + target)
		return
	}
	if _, err = f.WriteString(time.Now().UTC().Format(time.RFC1123)); err != nil {
		repo.Logger.Error("Unable to write to trace file: " + target)
		return
	}
}

func backupRsyncFailLog(repo *config.Repo) {
	src := repo.RsyncLogFile
	dest := repo.RsyncLogFile + ".fail"

	fin, err := os.Open(src)
	if err != nil {
		repo.Logger.Error(err.Error())
	}
	defer fin.Close()

	fout, err := os.OpenFile(dest, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
	if err != nil {
		repo.Logger.Error(err.Error())
	}
	defer fout.Close()

	if _, err = io.Copy(fout, fin); err != nil {
		repo.Logger.Error(err.Error())
	}
}
