#include "telnetd_cli.hpp"
#include <lib/cli/cli.hpp>
#include "telnetd.hpp"

static 
const cli::QCommandsDef<CLITelnetService> telnetserv_commands ={
    {"help", &CLITelnetService::cli_help_cmd, " this help", nullptr } ,
    {"start", &CLITelnetService::cli_start,   " port \t- startup telnet daemon on port <port>"
                                        , &CLITelnetService::evStartTelnetDaemon } ,
    {nullptr, &CLITelnetService::cli_help_cmd, nullptr, nullptr}
};

CLITelnetService::TelnetdEvent		CLITelnetService::evStartTelnetDaemon;

CLITelnetService::CLITelnetService(const_cmd _cmd, core_t& x)
: QObject(&x)
, inherited(_cmd, &x, telnetserv_commands)
{
    register_dummy_events();
}

int CLITelnetService::cli_start(CLI_shell* shell, const_line line){
    long portno = -1;
    auto cmd = cli::pass_number(portno, line);
    if (cmd == nullptr)
        return -1;
    if ((portno < 0) ||( portno > 0xffff)){
        shell->acceptChars(cmd);
        shell->puts("invalid port number value, valid 0...0xffff\n");
        return -1;
    }
    emit_event(this, CLITelnetService::evStartTelnetDaemon.dup().assign_port(portno) );
    return cmd-line;
}

//startup telnet daemon on port
void CLITelnetService::start_telnetd(quint16 port){
    core.logf(ILogger::vINFO, "core: start telnet on %u...\n", (unsigned)port);
    auto daemon = new TelnetDaemon(&core);
    bool ok = daemon->listen_local( port);
    if (ok) {
        core.logf( ILogger::vINFO, "core: started telnet on %u", (unsigned)port);
        connect(this, &CLITelnetService::destroy_all, daemon, &TelnetDaemon::destroy );
        connect(this, &CLITelnetService::shutdown_all, daemon, &TelnetDaemon::shutdown );
    }
    else {
        core.logf( ILogger::vERR, "core: failed telnet on %u", (unsigned)port);
        daemon->destroy();
    }
}

void CLITelnetService::destroy_demons(){
    emit destroy_all();
}

void CLITelnetService::shutdown_demons(){
    emit shutdown_all();
}


bool CLITelnetService::event(::QEvent *ev){
	if (ev->type() == evStartTelnetDaemon.type()){
		start_telnetd( ((TelnetdEvent*)ev)->port );
		return true;
	}
	return QObject::event(ev);
}





static 
const cli::QCommandsDef<CLITelnetDaemon> telnetd_commands ={
    {"help", &CLITelnetDaemon::cli_help_cmd, "\t- this help", nullptr } ,
    {"close", nullptr, "\t- stop daemon and close it" //&CLITelnetDaemon::cli_shutdown
                                            , &TelnetDaemon::evDestroy } ,
    {"shutdown", nullptr, "\t- close daemon and all it`s connections" //&CLITelnetDaemon::cli_shutdown
                                            , &TelnetDaemon::evShutdown } ,
    {nullptr, &CLITelnetDaemon::cli_help_cmd, nullptr, nullptr}
};

CLITelnetDaemon::CLITelnetDaemon(const std::string& _cmd, daemon_t& adaemon)
: inherited( _cmd.c_str(), &adaemon, telnetd_commands)
//, QObject(&adaemon) 
, _daemon(adaemon)
, name(_cmd)
{
    cmd_name = name.c_str();
    register_dummy_events();
}

CLITelnetDaemon::~CLITelnetDaemon(){
    cli::unregisterCmd(this);
}

int CLITelnetDaemon::cli_close(CLI_shell* shell, const_line line){
    shell->printf("close daemon %s\n", cmd_name);
    emit_event( TelnetDaemon::evDestroy.copy() );
    (void) line;
    return 0;
}

int CLITelnetDaemon::cli_shutdown(CLI_shell* shell, const_line line){
    shell->printf("down daemon %s connections\n", cmd_name);
    emit_event( TelnetDaemon::evShutdown.copy() );
    (void) line;
    return 0;
}
