package server

import (
	"net"

	"github.com/sjy-dv/scdb/cluster/config"
	"github.com/sjy-dv/scdb/cluster/scripts"
	"github.com/sjy-dv/scdb/cluster/store"
	"github.com/sjy-dv/scdb/scdb/pkg/log"
)

type App struct {
	listener net.Listener

	// wrapper and manager for db instance
	store *store.Store
}

func NewApp(cfg *config.Config) *App {
	var err error
	app := &App{}

	app.store, err = store.NewStore(cfg.RaftDir, cfg.RaftBind)
	if err != nil {
		log.Error(err.Error())
		panic(err.Error())
	}

	bootstrap := cfg.Join == ""
	err = app.store.Open(bootstrap, cfg.NodeID)
	if err != nil {
		log.Error(err.Error())
		panic(err.Error())
	}

	if !bootstrap {
		rc := scripts.NewClient(cfg.Join, "")
		log.Infof("join request send to %s", cfg.Join)
		_, err := rc.Do("join", cfg.RaftBind, cfg.NodeID)
		if err != nil {
			log.Error(err.Error())
		}
		rc.Close()
	}

	app.listener, err = net.Listen("tcp", cfg.Listen)
	log.Infof("server listen in %s", cfg.Listen)
	if err != nil {
		log.Error(err.Error())
	}
	return app
}

func (app *App) Run() {
	for {
		select {
		default:
			conn, err := app.listener.Accept()
			if err != nil {
				log.Warn(err.Error())
				continue
			}
			ClientHandler(conn, app)
		}
	}
}
