//Copyright 2017 Huawei Technologies Co., Ltd
//
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
package server

import (
	"fmt"
	"github.com/astaxie/beego"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"
)
import (
	"github.com/ServiceComb/service-center/pkg/common"
	"github.com/ServiceComb/service-center/server/api"
	"github.com/ServiceComb/service-center/server/core/registry"
	st "github.com/ServiceComb/service-center/server/core/registry/store"
	rs "github.com/ServiceComb/service-center/server/rest"
	"github.com/ServiceComb/service-center/server/service"
	nf "github.com/ServiceComb/service-center/server/service/notification"
	"github.com/ServiceComb/service-center/util"
	"golang.org/x/net/context"
	"runtime"
)

var (
	apiServer     *api.APIServer
	notifyService *nf.NotifyService
	store         *st.KvStore
	exit          chan struct{}
)

const CLEAN_UP_TIMEOUT = 5

func init() {
	util.LOGGER.Infof("service center have running simultaneously with %d CPU cores", runtime.GOMAXPROCS(0))

	exit = make(chan struct{})

	store = st.Store()

	notifyService = nf.GetNotifyService()

	apiServer = api.GetAPIServer()

	rs.ServiceAPI, rs.InstanceAPI, rs.GovernServiceAPI = service.AssembleResources()

	go handleSignal()
}

func Run() {
	beforeRun()

	waitStoreReady()

	startNotifyService()

	startApiServer()

	waitForQuit()
}

func beforeRun() {
	var client registry.Registry
	wait := []int{1, 1, 1, 5, 10, 20, 30, 60}
	for i := 0; client == nil; i++ {
		client = registry.GetRegisterCenter()
		if i >= len(wait) {
			i = len(wait) - 1
		}
		t := time.Duration(wait[i]) * time.Second
		util.LOGGER.Errorf(nil, "initialize service center failed, retry after %s", t)
		<-time.After(t)
	}
}

func handleSignal() {
	sc := make(chan os.Signal, 1)
	signal.Notify(sc, os.Interrupt)
	signal.Ignore(syscall.SIGQUIT) // when uses jstack to dump stack

	s := <-sc
	util.LOGGER.Warnf(nil, "Caught signal '%v', now service center quit...", s)

	close(exit)

	if apiServer != nil {
		apiServer.Stop()
	}

	if notifyService != nil {
		notifyService.Stop()
	}

	if store != nil {
		store.Stop()
	}

	util.GoCloseAndWait()

	registry.GetRegisterCenter().Close()
}

func waitForQuit() {
	var err error
	select {
	case err = <-apiServer.Err():
	case err = <-notifyService.Err():
	case <-exit:
	}
	if err != nil {
		util.LOGGER.Errorf(err, "service center catch errors, %s", err.Error())
	}
	select {
	case <-exit:
		util.LOGGER.Warnf(nil, "waiting for %ds to clean up resources...", CLEAN_UP_TIMEOUT)
		<-time.After(CLEAN_UP_TIMEOUT * time.Second)
	default:
		close(exit)
	}
	util.LOGGER.Warn("service center quit", nil)
}

func autoCompact() {
	compactTicker := time.NewTicker(time.Minute * 5)
	defer compactTicker.Stop()
	for t := range compactTicker.C {
		util.LOGGER.Debug(fmt.Sprintf("Compact at %s", t))
		registry.GetRegisterCenter().CompactCluster(context.TODO())
	}
}

func waitStoreReady() {
	store.Run()
	<-store.Ready()
}

func startNotifyService() {
	notifyService.Config = nf.NotifyServiceConfig{
		AddTimeout:    30 * time.Second,
		NotifyTimeout: 30 * time.Second,
		MaxQueue:      100,
	}
	notifyService.Start()
}

func startApiServer() {
	sslMode := common.GetServerSSLConfig().SSLEnabled
	verifyClient := common.GetServerSSLConfig().VerifyClient
	restIp := beego.AppConfig.String("httpaddr")
	restPort := beego.AppConfig.String("httpport")
	grpcIp := beego.AppConfig.DefaultString("grpcaddr", "")
	grpcPort := beego.AppConfig.DefaultString("grpcport", "")
	cmpName := beego.AppConfig.String("ComponentName")
	hostName := fmt.Sprintf("%s_%s", cmpName, strings.Replace(util.GetLocalIP(), ".", "_", -1))
	util.LOGGER.Infof("Local listen address: %s:%s, host: %s.", restIp, restPort, hostName)

	eps := map[api.APIType]string{}
	if len(restIp) > 0 && len(restPort) > 0 {
		eps[api.REST] = strings.Join([]string{restIp, restPort}, ":")
	}
	if len(grpcIp) > 0 && len(grpcPort) > 0 {
		eps[api.GRPC] = strings.Join([]string{grpcIp, grpcPort}, ":")
	}
	apiServer.Config = api.APIServerConfig{
		HostName:     hostName,
		Endpoints:    eps,
		SSL:          sslMode,
		VerifyClient: verifyClient,
	}
	apiServer.Start()
}
