package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"time"

	"config-server/bus"
	"config-server/conf"
	"config-server/log"

	"go.uber.org/dig"
	"infish.cn/comm"
)

var confFile = flag.String("conf", "./app.yaml", "conf file")

func StarProcc(dir string, name string, env []string, arg ...string) error {
	cmd := exec.Command(name, arg...)
	cmd.Dir = dir
	if len(env) > 0 {
		cmd.Env = env
	}
	var stdoutBuf, stderrBuf bytes.Buffer
	stdoutIn, _ := cmd.StdoutPipe()
	stderrIn, _ := cmd.StderrPipe()
	// var errStdout, errStderr error
	stdout := io.MultiWriter(os.Stdout, &stdoutBuf)
	stderr := io.MultiWriter(os.Stderr, &stderrBuf)
	go func() {
		io.Copy(stdout, stdoutIn)
	}()
	go func() {
		io.Copy(stderr, stderrIn)
	}()
	err := cmd.Start()
	if err != nil {
		fmt.Println(err)
		return err
	}
	fmt.Println(cmd.Process)

	// timout := time.After(time.Second * 5)
	// select {
	// case
	// case timoutTime := <-timout:
	// 	fmt.Println("started timenout", timoutTime)
	// 	return nil
	// }
	time.Sleep(2 * time.Second)

	fmt.Println("process status after 3 second ", cmd.ProcessState.ExitCode())

	return nil
}

func BuildApp() *dig.Container {
	app := dig.New()
	_ = app.Provide(func() (*conf.AppConf, error) {
		return conf.NewAppConf(*confFile)
	})
	_ = app.Provide(bus.NewNatsBus)
	return app
}

func main() {

	flag.Parse()
	app := BuildApp()

	fmt.Println(runtime.GOOS)
	fmt.Println(runtime.GOARCH)

	//启动nats
	err := app.Invoke(func(config *conf.AppConf) error {
		conf.AppConfig = config

		fmt.Println("nats config...", config.StartLocalNats, config.StartNatsPort, config.StartNatsShellParams)

		if !config.StartLocalNats { //是否启动nats
			return nil
		}
		envs := []string{}
		params := strings.Split(config.StartNatsShellParams, " ")
		wk := fmt.Sprintf("bin/v2.9.0/%s-%s", runtime.GOOS, runtime.GOARCH)
		fmt.Println("starting nats-server...", wk)

		err := StarProcc(wk, "./nats-server", envs, params...)
		if err != nil {
			return err
		}
		url := fmt.Sprintf("nats://127.0.0.1:%d", config.StartNatsPort)
		fmt.Println("started nats=>", url)

		return nil
	})
	if err != nil {
		log.Errorf("the nats service start fail %+v", err)
		panic(err)
	}

	if conf.AppConfig.StartLocalNats { //启动configer服务
		conf.AppConfig.Nats.Url = fmt.Sprintf("nats://127.0.0.1:%d", conf.AppConfig.StartNatsPort)
	}

	err = app.Invoke(func(config *conf.AppConf, nats *comm.NatsBus, adapters map[string]*comm.NatsBus) error {
		for _, remote := range adapters {
			if remote != nil {
				go remote.Run(nil)
			}
		}

		nats.Run(nil)
		return nil
	})

	if err != nil {
		log.Errorf("the configer service quit fail %+v", err)
		panic(err)
	}
}
