package main

import (
	"flag"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"github.com/ngaut/log"
	"github.com/pingcap/schrodinger/agent/api"
	"github.com/pingcap/schrodinger/agent/client"
	"github.com/pingcap/schrodinger/util"
)

var defaultDaemonArgs []string
var (
	pprofAddr          string
	agentAddr          string
	logFile            string
	logLevel           string
	daemon             string
	binaryAddr         string
	binaryName         string
	daemonArgs         string
	daemonRestartLimit int
	daemonTimeout      int
	printVersion       bool
)

func init() {
	flag.StringVar(&pprofAddr, "pprof", "0.0.0.0:10080", "agent pprof address")
	flag.StringVar(&agentAddr, "addr", "0.0.0.0:8080", "agent listen address")
	flag.StringVar(&logFile, "log-file", "", "agent log file")
	flag.StringVar(&logLevel, "log-level", "info", "agent log level: info, warn, fatal, error")
	flag.StringVar(&daemon, "daemon", "", "default daemon process name")
	flag.StringVar(&binaryAddr, "binary-addr", "", "default daemon binary address")
	flag.StringVar(&binaryName, "binary-name", "", "default daemon binary name")
	flag.StringVar(&daemonArgs, "daemon-args", "", "default daemon args")
	flag.IntVar(&daemonRestartLimit, "daemon-restart", 0, "daemon restart limit")
	flag.IntVar(&daemonTimeout, "daemon-timeout", 0, "default daemon agent daemon timeout")
	flag.BoolVar(&printVersion, "V", false, "print version")
}

func main() {
	flag.Parse()
	if printVersion {
		util.PrintInfo()
		os.Exit(0)
	}

	defaultDaemonArgs = extractArgs()
	initLogger()
	go func() {
		if err := http.ListenAndServe(pprofAddr, nil); err != nil {
			log.Fatal(err)
		}
	}()

	log.Infof("begin to listen %s", agentAddr)
	a := api.NewAgent(agentAddr)
	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

	go func() {
		a.Run()
	}()
	time.Sleep(time.Second)
	if binaryAddr != "" && binaryName != "" {
		runDefaultDaemon()
	}

	<-sigs
	log.Info("closing agent")
	a.Close()
	log.Info("agent is closed")
}

func initLogger() {
	log.SetLevelByString(logLevel)

	if len(logFile) > 0 {
		log.SetOutputByName(logFile)
		log.SetRotateByDay()
	}
}

func extractArgs() []string {
	rawArgs := strings.Split(strings.Trim(daemonArgs, "\""), " ")
	args := make([]string, 0, len(rawArgs))
	for _, arg := range rawArgs {
		arg = strings.TrimSpace(arg)
		if arg == "" {
			continue
		}
		args = append(args, arg)
	}

	return args
}

/*func extractArgs() []string {
	var args = make([]string, 0, len(os.Args))
	daemonArgs := make([]string, 0, len(os.Args))
	args = append(args, os.Args[0])

	for i := 1; i < len(os.Args); i++ {
		arg := os.Args[i]
		val := ""
		hasVal := false
		if i+1 < len(os.Args) && !strings.HasPrefix(os.Args[i+1], "-") {
			hasVal = true
			i++
			val = os.Args[i]
		}

		if arg == "-V" || arg == "--V" {
			args = append(args, arg)
			os.Args = args
			return nil
		}
		if arg == "--help" || arg == "-help" {
			args = append(args, arg)
			os.Args = args
			return nil
		}

		if strings.HasPrefix(arg, "--agent") || strings.HasPrefix(arg, "-agent") {
			args = append(args, arg)
			if hasVal {
				args = append(args, val)
			}
		} else {
			daemonArgs = append(daemonArgs, arg)
			if hasVal {
				daemonArgs = append(daemonArgs, val)
			}
		}
	}

	os.Args = args
	return daemonArgs
}*/

func runDefaultDaemon() {
	if daemon == "" {
		daemon = binaryName
	}

	svr := strings.Replace(agentAddr, "0.0.0.0", "127.0.0.1", 1)
	err := client.NewClient(svr).StartProcess(daemon, binaryName, binaryAddr, defaultDaemonArgs, int32(daemonRestartLimit), 1, time.Duration(daemonTimeout))
	if err != nil {
		log.Fatalf("start default daemon error %v", err)
	}
}
