#include <config.h>
#include <stdio.h>
#include "IMSvr.hh"
#include "IMSvrCfg.hh"
#include "IMConnection.hh"
#include "LEMgr.hh"
#include "IIIMProtocol.hh"
#include "IMScheduler.hh"

bool
IMSvr::config_lepath(
    const char *lepath
)
{
    LEMgr *plm = new LEMgr(lepath);
    if (!plm) return false;
    if (plemgr) delete plemgr;
    plemgr = plm;
    return true;
}

bool
IMSvr::config_le (
    const char *lepath,
    IIIMLEXMLConf &xml,
    bool preferred_loading
)
{
    LEMgr *plm = new LEMgr (lepath, xml, preferred_loading);

    if (!plm)
	return false;
    if (plemgr)
	delete plemgr;
    plemgr = plm;

    return true;
}

bool
IMSvr::set_nsmap_config (
    IMNsMapStruct *nsmp,
    int num_entries
)
{
    plemgr->set_nsmap_config(nsmp, num_entries);
    return true;
}

bool
IMSvr::config_listenaddress(
    IMSocketAddressVec& addrvec
)
{
    IIIMProtocol *pimp = new IIIMProtocol(this);
    if (!pimp) return false;

    pimp->set_server_listen_address(addrvec);
    if (pimprotocol)
	delete pimprotocol;
    pimprotocol = pimp;

    return true;
}

IMKeySpecList
IMSvr::get_conversionkeys() const
{
    return IMKeyParser(pcfg->get_strval(IMSvrCfg::CONVERSIONKEYS)).get_parsedkeys();
}

int
IMSvr::start()
{
    if (!pcfg->configure(this)) return IMSVR_CONFIG_ERROR;
    ASSERT(plemgr);
    ASSERT(pimprotocol);

    for(;;) {
        IMState *pims = pimprotocol->accept();
        if (pims) {
            IMScheduler::get_instance()->start(this, pimprotocol, pims);
        }
        if (signal_flag.test(CAUGHT_SIGHUP)) {
            // received HUP signal
            plemgr->reload();
        }
        if (signal_flag.test(CAUGHT_SIGTERM)) {
            // received TERM signal
            break;
        }
        signal_flag.reset();
    }

    return IMSVR_EXIT_SUCCESS;
}

void
IMSvr::reload()
{
    // NOTICE:
    // this function is called by signal handler.
    // so we must use signal-safe function in it.
    signal_flag.set(CAUGHT_SIGHUP, true);
}

void
IMSvr::terminate()
{
    // NOTICE:
    // this function is called by signal handler.
    // so we must use signal-safe function in it.
    signal_flag.set(CAUGHT_SIGTERM, true);
    return;
}

bool
IMSvr::request_accept(
    int fd
)
{
    if (usermgr.fd_ok(fd)) return true;

    return false;
}

IMConnection*
IMSvr::create_imconnection(
    IMUser *puser,
    const string &hostname
)
{
    IMConnection* pc;

    pc = new IMConnection(this, puser, hostname);
    if (!pc) return NULL;

    return pc;
}

IMHandler*
IMSvr::request_connect(
    int fd,
    const u16string &username,
    const string &hostname,
    const u16string &password,
    const IMAuthList &authlist
)
{
    IMUser *puser;
    IMConnection *pimc;

    // TODO
    if (!username.get_charstr()) return NULL;
    puser = usermgr.create_imuser(fd, username.get_charstr(), password.get_charstr());
    if (!puser) return NULL;
    pimc = create_imconnection(puser, hostname);
    if (!pimc) return NULL;

    return pimc;
}

IMSvr::IMSvr(
    IMSvrCfg *p_cfg
) :
    pcfg(p_cfg)
{
    plemgr = NULL;
    pimprotocol = NULL;
}

IMSvr::~IMSvr()
{
    if (plemgr) delete plemgr;
    if (pimprotocol) delete pimprotocol;
}

/* Local Variables: */
/* c-file-style: "iiim-project" */
/* End: */
