package main

import (
	"flag"
	"fmt"
	"github.com/huichen/wukong/types"
	"os"
	"os/signal"
	"syscall"
	"time"
)

import (
	wukong "github.com/huichen/wukong/engine"
)

/**
wukongd 基于 wukong 实现，内置一个 http server. 和一个启动配置文件

* 支持字符串索引

多实例部署可直接启动多个实例，http 客户端来实现索引的 hash-sharding 以及 查询汇总

*/

var (
	searcher    = wukong.Engine{}
	confile     = flag.String("c", "wukongd.conf", "specify the config file")
	test_conf   = flag.String("t", "", "test specified config file")
	showVersion = flag.Bool("v", false, "display version")

	chSig     = make(chan os.Signal, 2)
	startedAt = time.Now()
)

func _main() {
	flag.Parse()

	var err error
	// version
	if *showVersion {
		printVersion()
		return
	}
	// check config
	if len(*test_conf) > 0 {
		_, err := loadConfig(*test_conf)
		if err != nil {
			fmt.Printf("check config file %s failed: %s.\n", *test_conf, err)
			return
		}
		fmt.Printf("check config file %s succeed.\n", *test_conf)
		return
	}
	// main
	config, err = loadConfig(*confile)
	if err != nil {
		fmt.Printf("check config file %s failed: %v\n", *confile, err)
		return
	}

	printBaseInfo()

	// init logger
	initLogger(config.Logger.Console, config.Logger.File, config.Logger.Level)

	// init engine
	options := types.RankOptions{
		OutputOffset: config.Engine.OutputOffset,
		MaxOutputs:   config.Engine.MaxOutput,
	}
	searcher.Init(types.EngineInitOptions{
		SegmenterDictionaries: config.Engine.Dictionary,
		StopTokenFile:         config.Engine.Stoptoken,
		IndexerInitOptions: &types.IndexerInitOptions{
			IndexType: config.Engine.IndexType,
		},
		NumShards:               config.Engine.ShardsNum,
		DefaultRankOptions:      &options,
		UsePersistentStorage:    config.Engine.Persistent,
		PersistentStorageEngine: config.Engine.PersistentEngine,
		PersistentStorageFolder: config.Engine.PersistentFolder,
		PersistentStorageShards: config.Engine.PersistentShardsNum,
	})
	searcher.FlushIndex()
	logger.Info().Uint64("indexed", searcher.NumDocumentsIndexed()).Msg("index finished")
	// init http
	err = startHttp(config.Server.Addr)
	if err != nil {
		panic(err)
	}
	logger.Info().Str("addr", config.Server.Addr).Msg("server started")

	signal.Notify(chSig, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)

	sig := <-chSig
	logger.Info().Str("signal", sig.String()).Msg("received signal, stopping")

	stopHttp()
	searcher.Close()

	logger.Info().Msg("server stopped")
}

func printBaseInfo() {
	fmt.Printf(`%s-%s build %s
listen address: %s
running mode: %s
db location: %s
log location: %s
log level: %s
`, name, version, gitCommit, config.Server.Addr,
		config.Server.Mode,
		config.Engine.PersistentFolder,
		config.Logger.File,
		config.Logger.Level)
}

func main() {
	_main()
}
