package TelnetShellServer

import (
	"github.com/reiver/go-oi"
	"github.com/reiver/go-telnet"
	"github.com/reiver/go-telnet/telsh"
	"proxy/canal"
	"proxy/config"

	"io"

	sdb "proxy/Nmysql"
	rdb "proxy/Nredis"
)

// Command not found!
func notFoundHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
	_, _ = oi.LongWriteString(stdout, "\rCommand not found!")
	_, _ = oi.LongWriteString(stdout, "\n\r")
	_, _ = oi.LongWriteString(stdout, "")

	return nil
}

// Syn DB
func syncDbHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
	//rdb.ClrTariffAndBundle()
	_ = sdb.LoadAcctTblFromMysql()
	_, _ = oi.LongWriteString(stdout, "\rSync DB, done!")
	_, _ = oi.LongWriteString(stdout, "\n\r")
	_, _ = oi.LongWriteString(stdout, "")

	return nil
}

// Syn msisdn
func syncMsisdnHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
	//rdb.ClrTariffAndBundle()
	_ = sdb.LoadOneAcctFromMysql(args[1])
	_, _ = oi.LongWriteString(stdout, "\rSync DB, done!")
	_, _ = oi.LongWriteString(stdout, "\n\r")
	_, _ = oi.LongWriteString(stdout, "")

	return nil
}

func syncDbProducer(ctx telnet.Context, name string, args ...string) telsh.Handler{
	if len(args) > 0 {
		if args[0] == "db" {
			return telsh.PromoteHandlerFunc(syncDbHandler)
		} else if args[0] == "msisdn" && len(args)>=2 {
			return telsh.PromoteHandlerFunc(syncMsisdnHandler, args...)
		} else {
			return telsh.PromoteHandlerFunc(notFoundHandler)
		}
	} else {
		return telsh.PromoteHandlerFunc(notFoundHandler)
	}
}

// Clr DB
func clearDbHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
	rdb.ClrTariffAndBundle()
	_, _ = oi.LongWriteString(stdout, "\rClear DB Finish!")
	_, _ = oi.LongWriteString(stdout, "\n\r")
	_, _ = oi.LongWriteString(stdout, "")

	return nil
}

// Clr Expired rr
func clearRrHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
	rdb.ClrExpRes()
	_, _ = oi.LongWriteString(stdout, "\rClear Expired RR Finish!")
	_, _ = oi.LongWriteString(stdout, "\n\r")
	_, _ = oi.LongWriteString(stdout, "")

	return nil
}

func clearDbProducer(ctx telnet.Context, name string, args ...string) telsh.Handler{
	if len(args) > 0 {
		if args[0] == "db" {
			return telsh.PromoteHandlerFunc(clearDbHandler)
		} else if args[0] == "rr" {
			return telsh.PromoteHandlerFunc(clearRrHandler)
		} else {
			return telsh.PromoteHandlerFunc(notFoundHandler)
		}
	} else {
		return telsh.PromoteHandlerFunc(notFoundHandler)
	}
}

// get ofr
func getOfrHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
	rdb.RdbGetTariffByOfrId(args[1])
	_, _ = oi.LongWriteString(stdout, "\rGet ofr Finish!")
	_, _ = oi.LongWriteString(stdout, "\n\r")
	_, _ = oi.LongWriteString(stdout, "")

	return nil
}

// get act
func getActHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
	//_, _ = oi.LongWriteString(stdout, "\n\rdebug2, len(args)="+fmt.Sprintf("%d:%v", len(args), args))
	rsp, _ := rdb.RdbGetAcctRecordByServiceNbr(args[1])
	_, _ = oi.LongWriteString(stdout, "\r"+rsp+"\n\rGet acct Finish!")
	_, _ = oi.LongWriteString(stdout, "\n\r")
	_, _ = oi.LongWriteString(stdout, "")

	return nil
}

// get rat
func getRatHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
	rsp, _ := rdb.RdbGetRrByServiceNbrAndDomain(args[1])
	_, _ = oi.LongWriteString(stdout, "\r"+rsp+"\n\rGet Rr Finish!")
	_, _ = oi.LongWriteString(stdout, "\n\r")
	_, _ = oi.LongWriteString(stdout, "")

	return nil
}

// get state
func getStateHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
	var state string
	/*if rdb.CheckIfRdbMaster() == true {
		state = "Redis: master; state: " + canal.CurState
	} else {*/
		state = "Redis: master; state: " + canal.CurState
	//}
	_, _ = oi.LongWriteString(stdout, "\r"+state)
	_, _ = oi.LongWriteString(stdout, "\n\r")
	_, _ = oi.LongWriteString(stdout, "")

	return nil
}

func getRecordProducer(ctx telnet.Context, name string, args ...string) telsh.Handler{
	if len(args) >= 2 {
		/*if args[0] == "ofr" {
			return telsh.PromoteHandlerFunc(getOfrHandler)
		} else */if args[0] == "act" {
			return telsh.PromoteHandlerFunc(getActHandler, args...)
		} else if args[0] == "rat" {
			return telsh.PromoteHandlerFunc(getRatHandler, args...)
		} else if args[0] == "state" {
			return telsh.PromoteHandlerFunc(getStateHandler, args...)
		} else {
			return telsh.PromoteHandlerFunc(notFoundHandler)
		}
	} else if len(args) == 1 {
		if args[0] == "state" {
			return telsh.PromoteHandlerFunc(getStateHandler)
		} else {
			return telsh.PromoteHandlerFunc(notFoundHandler)
		}
	} else {
		return telsh.PromoteHandlerFunc(notFoundHandler)
	}
}

// enable bundle notify
func enableVoiceBundleNtfHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
	config.SetBundleUsageNtf(1, true)
	_, _ = oi.LongWriteString(stdout, "\r"+"Comand OK")
	_, _ = oi.LongWriteString(stdout, "\n\r")
	_, _ = oi.LongWriteString(stdout, "")

	return nil
}

func enableDataBundleNtfHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
	config.SetBundleUsageNtf(2, true)
	_, _ = oi.LongWriteString(stdout, "\r"+"Comand OK")
	_, _ = oi.LongWriteString(stdout, "\n\r")
	_, _ = oi.LongWriteString(stdout, "")

	return nil
}

func enableSmsBundleNtfHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
	config.SetBundleUsageNtf(3, true)
	_, _ = oi.LongWriteString(stdout, "\r"+"Comand OK")
	_, _ = oi.LongWriteString(stdout, "\n\r")
	_, _ = oi.LongWriteString(stdout, "")

	return nil
}

func enableParamProducer(ctx telnet.Context, name string, args ...string) telsh.Handler{
	if len(args) == 1 {
		if args[0] == "voc75ntf" {
			return telsh.PromoteHandlerFunc(enableVoiceBundleNtfHandler)
		} else if args[0] == "dat75ntf" {
			return telsh.PromoteHandlerFunc(enableDataBundleNtfHandler)
		} else if args[0] == "sms75ntf" {
			return telsh.PromoteHandlerFunc(enableSmsBundleNtfHandler)
		} else {
			return telsh.PromoteHandlerFunc(notFoundHandler)
		}
	} else {
		return telsh.PromoteHandlerFunc(notFoundHandler)
	}
}

// disable bundle notify
func disableVoiceBundleNtfHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
	config.SetBundleUsageNtf(1, false)
	_, _ = oi.LongWriteString(stdout, "\r"+"Comand OK")
	_, _ = oi.LongWriteString(stdout, "\n\r")
	_, _ = oi.LongWriteString(stdout, "")

	return nil
}

func disableDataBundleNtfHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
	config.SetBundleUsageNtf(2, false)
	_, _ = oi.LongWriteString(stdout, "\r"+"Comand OK")
	_, _ = oi.LongWriteString(stdout, "\n\r")
	_, _ = oi.LongWriteString(stdout, "")

	return nil
}

func disableSmsBundleNtfHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
	config.SetBundleUsageNtf(3, false)
	_, _ = oi.LongWriteString(stdout, "\r"+"Comand OK")
	_, _ = oi.LongWriteString(stdout, "\n\r")
	_, _ = oi.LongWriteString(stdout, "")

	return nil
}

func disableParamProducer(ctx telnet.Context, name string, args ...string) telsh.Handler{
	if len(args) == 1 {
		if args[0] == "voc75ntf" {
			return telsh.PromoteHandlerFunc(disableVoiceBundleNtfHandler)
		} else if args[0] == "dat75ntf" {
			return telsh.PromoteHandlerFunc(disableDataBundleNtfHandler)
		} else if args[0] == "sms75ntf" {
			return telsh.PromoteHandlerFunc(disableSmsBundleNtfHandler)
		} else {
			return telsh.PromoteHandlerFunc(notFoundHandler)
		}
	} else {
		return telsh.PromoteHandlerFunc(notFoundHandler)
	}
}

/* version handler
func versionHandler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
	oi.LongWriteString(stdout, "\rCurrent PCF version:\n\r")
	oi.LongWriteString(stdout, "\r" + n.GetPcfVersion())
	oi.LongWriteString(stdout, "\n\r")
	oi.LongWriteString(stdout, "")

	return nil
}

func versionProducer(ctx telnet.Context, name string, args ...string) telsh.Handler{
	return telsh.PromoteHandlerFunc(versionHandler)
}*/

func Server(addr string) {

	shellHandler := telsh.NewShellHandler()

	shellHandler.WelcomeMessage = `
 __          __ ______  _        _____   ____   __  __  ______ 
 \ \        / /|  ____|| |      / ____| / __ \ |  \/  ||  ____|
  \ \  /\  / / | |__   | |     | |     | |  | || \  / || |__   
   \ \/  \/ /  |  __|  | |     | |     | |  | || |\/| ||  __|  
    \  /\  /   | |____ | |____ | |____ | |__| || |  | || |____ 
     \/  \/    |______||______| \_____| \____/ |_|  |_||______|

\033[2J\033[1;1HAVAILABLE COMMANDS\n" +
========================================================================
| Command              |  Remark                                        |
========================================================================
| help                 |  Help page.                                    |
| date                 |  Current date.                                 |
| syn db               |  Syn Mysql DB to Redis DB.                     |
| clr db               |  Clear Redis DB.                               |
| clr rr               |  Clear Expired RR.                             |
| get state            |  Get loading/init state.                       |
| get act serviceNbr   |  Get acct info by service number.              |
| get rat num:domain   |  Get RR info by service number and domain.     |
| [en|dis]able voc75ntf|  Enable[Disable] %75 usage of voice bundle.    |
| [en|dis]able dat75ntf|  Enable[Disable] %75 usage of data bundle.     |
| [en|dis]able sms75ntf|  Enable[Disable] %75 usage of sms bundle.      |
| q                    |  Quit.                                         |
========================================================================
`
	//shellHandler.Prompt = "pcf:~$"
	shellHandler.ExitCommandName = "q"
	shellHandler.ExitMessage = "Good bye...\r\n"

	// Register the "sync db" command.
	commandName     := "syn"
	commandProducer := telsh.ProducerFunc(syncDbProducer)
	_ = shellHandler.Register(commandName, commandProducer)

	// Register the "clear db" command.
	commandName     = "clr"
	commandProducer = clearDbProducer
	_ = shellHandler.Register(commandName, commandProducer)

	commandName     = "get"
	commandProducer = getRecordProducer
	_ = shellHandler.Register(commandName, commandProducer)

	commandName     = "enable"
	commandProducer = enableParamProducer
	_ = shellHandler.Register(commandName, commandProducer)

	commandName     = "disable"
	commandProducer = disableParamProducer
	_ = shellHandler.Register(commandName, commandProducer)

	// Register the "version" command.
	//commandName     = "version"
	//commandProducer = telsh.ProducerFunc(versionProducer)
	//shellHandler.Register(commandName, commandProducer)

	if err := telnet.ListenAndServe(addr, shellHandler); nil != err {
		panic(err)
	}
}
