package main

import (
	"flag"
	"log"
	"os"
	"path"
	"path/filepath"

	"srs.epita.fr/fic-server/admin/sync"
	"srs.epita.fr/fic-server/libfic"
)

func main() {
	cloudDAVBase := ""
	cloudUsername := "fic"
	cloudPassword := ""
	localImporterDirectory := ""

	// Read paremeters from environment
	if v, exists := os.LookupEnv("FICCLOUD_URL"); exists {
		cloudDAVBase = v
	}
	if v, exists := os.LookupEnv("FICCLOUD_USER"); exists {
		cloudUsername = v
	}
	if v, exists := os.LookupEnv("FICCLOUD_PASS"); exists {
		cloudPassword = v
	}

	// Read parameters from command line
	flag.StringVar(&localImporterDirectory, "localimport", localImporterDirectory,
		"Base directory where to find challenges files to import, local part")
	flag.StringVar(&cloudDAVBase, "clouddav", cloudDAVBase,
		"Base directory where to find challenges files to import, cloud part")
	flag.StringVar(&cloudUsername, "clouduser", cloudUsername, "Username used to sync")
	flag.StringVar(&cloudPassword, "cloudpass", cloudPassword, "Password used to sync")
	flag.Var(&sync.RemoteFileDomainWhitelist, "remote-file-domain-whitelist", "List of domains which are allowed to store remote files")
	flag.Parse()

	// Do not display timestamp
	log.SetFlags(0)

	// Instantiate importer
	regenImporter := false
	if localImporterDirectory != "" {
		sync.GlobalImporter = sync.LocalImporter{Base: localImporterDirectory, Symlink: true}
	} else if cloudDAVBase != "" {
		sync.GlobalImporter, _ = sync.NewCloudImporter(cloudDAVBase, cloudUsername, cloudPassword)
	} else {
		// In this case, we want to treat the entier path given
		regenImporter = true
	}

	for _, p := range flag.Args() {
		if regenImporter {
			var err error
			p, err = filepath.Abs(p)
			if err != nil {
				p = path.Clean(p)
			}
			sync.GlobalImporter = sync.LocalImporter{
				Base:    p,
				Symlink: true,
			}
		}

		// Find all challenge.toml or challenge.txt
		treatDir("")
	}
}

func treatDir(p string) {
	var expath string

	for _, f := range []string{"challenge.toml", "challenge.txt"} {
		if sync.GlobalImporter.Exists(path.Join(p, f)) {
			expath = p
			break
		}
	}

	if expath != "" {
		treatExercice(expath)
	} else {
		files, err := sync.GlobalImporter.ListDir(p)
		if err != nil {
			log.Printf("Unable to readdir at %s: %s", p, err.Error())
			return
		}

		for _, f := range files {
			st, err := sync.GlobalImporter.Stat(path.Join(p, f))
			if err == nil && st.IsDir() {
				treatDir(path.Join(p, f))
			}
		}
	}
}

func treatExercice(expath string) {
	// Load exercice
	exercice, _, _, _, _, err := sync.BuildExercice(sync.GlobalImporter, &fic.Theme{}, expath, nil, nil)
	if exercice == nil {
		log.Printf("Unable to treat exercice %q: %s", expath, err.Error())
		return
	}

	paramsFiles, err := sync.GetExerciceFilesParams(sync.GlobalImporter, exercice)
	if err != nil {
		log.Printf("Unable to read challenge.toml %q: %s", expath, err.Error())
		return
	}

	for fname, pf := range paramsFiles {
		if pf.URL == "" {
			continue
		}

		dest := path.Join(exercice.Path, "files", fname)

		log.Printf("Downloading %s...", fname)
		if li, ok := sync.GlobalImporter.(sync.LocalImporter); ok {
			err = sync.DownloadExerciceFile(paramsFiles[fname], li.GetLocalPath(dest), exercice, false)
		} else {
			err = sync.DownloadExerciceFile(paramsFiles[fname], dest, exercice, false)
		}

		if err != nil {
			log.Println("DownloadExerciceFile error:", err.Error())
		}
	}
}
