package commands

import (
	"context"
	"flag"
	"os"

	"github.com/google/subcommands"
	"github.com/inconshreveable/log15"
	c "github.com/mozqnet/go-exploitdb/config"
	server "github.com/mozqnet/go-exploitdb/server"
	"github.com/mozqnet/go-exploitdb/util"
)

// ServerCmd :
type ServerCmd struct {
	Debug    bool
	DebugSQL bool
	Quiet    bool
	LogDir   string
	LogJSON  bool
	DBpath   string
	DBtype   string
	Bind     string
	Port     string
}

// Name :
func (*ServerCmd) Name() string { return "server" }

// Synopsis :
func (*ServerCmd) Synopsis() string { return "Start go-exploitdb HTTP server." }

// Usage :
func (*ServerCmd) Usage() string {
	return `server:
	server
		[-bind=127.0.0.1]
		[-port=8000]
		[-dbpath=$PWD/exploitdb.sqlite3 or connection string]
		[-dbtype=sqlite3|mysql|postgres|redis]
		[-debug]
		[-debug-sql]
		[-quiet]
		[-log-dir=/path/to/log]
		[-log-json]

  Command:
	$ go-exploitdb server

`
}

// SetFlags :
func (p *ServerCmd) SetFlags(f *flag.FlagSet) {
	f.BoolVar(&p.Debug, "debug", false, "debug mode (default: false)")
	f.BoolVar(&p.DebugSQL, "debug-sql", false, "SQL debug mode (default: false)")
	f.BoolVar(&p.Quiet, "quiet", false, "quiet mode (no output)")

	defaultLogDir := util.GetDefaultLogDir()
	f.StringVar(&p.LogDir, "log-dir", defaultLogDir, "/path/to/log")
	f.BoolVar(&p.LogJSON, "log-json", false, "output log as JSON")

	pwd := os.Getenv("PWD")
	f.StringVar(&p.DBpath, "dbpath", pwd+"/go-exploitdb.sqlite3",
		"/path/to/sqlite3 or SQL connection string")

	f.StringVar(&p.DBtype, "dbtype", "sqlite3",
		"Database type to store data in (sqlite3 or mysql supported)")

	f.StringVar(&p.Bind,
		"bind",
		"127.0.0.1",
		"HTTP server bind to IP address (default: loop back interface)")
	f.StringVar(&p.Port, "port", "1326",
		"HTTP server port number")
}

// Execute :
func (p *ServerCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
	c.CommonConf.Quiet = p.Quiet
	c.CommonConf.DebugSQL = p.DebugSQL
	c.CommonConf.Debug = p.Debug
	c.CommonConf.DBPath = p.DBpath
	c.CommonConf.DBType = p.DBtype
	c.ServerConf.Bind = p.Bind
	c.ServerConf.Port = p.Port

	util.SetLogger(p.LogDir, c.CommonConf.Quiet, c.CommonConf.Debug, p.LogJSON)
	if !c.CommonConf.Validate() {
		return subcommands.ExitUsageError
	}

	log15.Info("Starting HTTP Server...")
	if err := server.Start(p.LogDir); err != nil {
		log15.Error("Failed to start server", "err", err)
		return subcommands.ExitFailure
	}
	return subcommands.ExitSuccess
}
