package main

import (
	"flag"
	"net/http"
	_ "net/http/pprof"
	"os"
	"path/filepath"

	"github.com/pingcap/log"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/tidbcloud/ffs/client"
	"github.com/tidbcloud/ffs/util/logutil"
)

var (
	universe      = flag.String("universe", "localhost:9091,localhost:19091,localhost:29091", "The universe endpoints in the format of host:port,host:port")
	zone          = flag.String("zone", "zone-1", "The zone name")
	tenant        = flag.String("tenant", "tenant-1", "The tenant name")
	statusAddr    = flag.String("status-addr", "localhost:6069", "status address")
	volume        = flag.String("volume", "volume-1", "The volume id of ffs client")
	target        = flag.String("target", "/mnt", "The target path of ffs client")
	merge         = flag.Bool("merge", false, "merge fs")
	logLevel      = flag.String("log-level", "info", "log level: info, debug, warn, error, fatal")
	cacheRoot     = flag.String("cache-dir", "", "The cache directory of rfs client")
	cacheCapacity = flag.Int("cache-cap", 1073741824, "The cache capacity of rfs client")
	keepCache     = flag.Bool("keep-cache", true, "The file uses FOPEN_KEEP_CACHE flag")
	asyncWrite    = flag.Bool("async-write", true, "Writes bytes asynchronously")
	remove        = flag.Bool("remove", false, "remove volume")
	uid           = flag.Uint("uid", 0, "The uid used for filesystem")
	gid           = flag.Uint("gid", 0, "The gid used for filesystem")
)

var (
	gitHash = "None"
)

func main() {
	flag.Parse()
	logutil.SetLevel(*logLevel)
	log.S().Infof("gitHash: %s", gitHash)

	http.Handle("/metrics", promhttp.Handler())
	go http.ListenAndServe(*statusAddr, nil)

	target, err := filepath.Abs(*target)
	if err != nil {
		log.S().Fatalf("Failed to get abs file path:%v", target)
		return
	}
	var cacheDir string
	if len(*cacheRoot) > 0 {
		cacheDir, err = filepath.Abs(*cacheRoot)
		if err != nil {
			log.S().Fatalf("Failed to get abs cache path:%v", cacheRoot)
			return
		}
		os.RemoveAll(cacheDir)
		if err := os.MkdirAll(cacheDir, os.ModePerm); err != nil {
			log.S().Fatalf("Failed to mkdir cache path:%v", cacheDir)
		}
	}
	options := client.ClientOptions{
		Universe:   *universe,
		Zone:       *zone,
		Tenant:     *tenant,
		Volume:     *volume,
		Target:     target,
		Merged:     *merge,
		AsyncWrite: *asyncWrite,
		CacheDir:   cacheDir,
		CacheCap:   *cacheCapacity,
		KeepCache:  *keepCache,
		Uid:        uint32(*uid),
		Gid:        uint32(*gid),
	}
	if *remove {
		client.RemoveMount(&options)
		return
	}
	server := client.MustMount(&options)
	go server.ListenForUnmount()
	log.S().Infof("Mounted to %q, use ctrl+c to terminate.", target)
	server.Wait()
	server.Stop()
}
