/*!
  \~english
  Returns the rendering data of the partial template given by \a templateName.

  \~japanese
  部分テンプレート \a templateName に変数 \a vars を設定した描画データを返す
*/
QString TActionController::getRenderingData(const QString &templateName, const QVariantHash &vars)
{
    T_TRACEFUNC("templateName: %s", qPrintable(templateName));

    // Creates view-object
    QStringList names = templateName.split("/");
    if (names.count() != 2) {
        tError("Invalid patameter: %s", qPrintable(templateName));
        return QString();
    }

    TDispatcher<TActionView> viewDispatcher(viewClassName(names[0], names[1]));
    TActionView *view = viewDispatcher.object();
    if (!view) {
        return QString();
    }

    QVariantHash hash = allVariants();
    for (QHashIterator<QString, QVariant> i(vars); i.hasNext(); ) {
        i.next();
        hash.insert(i.key(), i.value()); // item's value of same key is replaced
    }

    view->setController(this);
    view->setVariantHash(hash);
    return view->toString();  
}
/*!
  \~english
  Renders the \a view view.

  \~japanese
  ビューを描画する
*/
QByteArray TActionController::renderView(TActionView *view)
{
    T_TRACEFUNC("view: %p  layout: %s", view, qPrintable(layout()));

    if (!view) {
        tSystemError("view null pointer.  action:%s", qPrintable(activeAction()));
        return QByteArray();
    }
    view->setController(this);
    view->setVariantHash(allVariants());

    if (!layoutEnabled()) {
        // Renders without layout
        tSystemDebug("Renders without layout");
        return Tf::app()->codecForHttpOutput()->fromUnicode(view->toString());
    }
  
    // Displays with layout
    QString lay = (layout().isNull()) ? name().toLower() : layout().toLower();
    TDispatcher<TActionView> layoutDispatcher(layoutClassName(lay));
    TActionView *layoutView = layoutDispatcher.object();

    TDispatcher<TActionView> defLayoutDispatcher(layoutClassName("application"));
    if (!layoutView) {
        if (!layout().isNull()) {
            tSystemDebug("Not found layout: %s", qPrintable(layout()));
            return QByteArray();
        } else {
            // Use default layout
            layoutView = defLayoutDispatcher.object();
            if (!layoutView) {
                tSystemDebug("Not found default layout. Renders without layout.");
                return Tf::app()->codecForHttpOutput()->fromUnicode(view->toString());
            }
        }
    }

    // Renders layout
    layoutView->setVariantHash(allVariants());
    layoutView->setController(this);
    layoutView->setSubActionView(view);
    return Tf::app()->codecForHttpOutput()->fromUnicode(layoutView->toString());
}
/*!
  Delivers an email generated by setting variables to the specified template.
*/
bool TActionMailer::deliver(const QString &templateName)
{
    // Creates the view-object
    TDispatcher<TActionView> viewDispatcher(viewClassName(CONTROLLER_NAME, templateName));
    TActionView *view = viewDispatcher.object();
    if (!view) {
        tSystemError("no such template : %s", qPrintable(templateName));
        return false;
    }

    view->setVariantMap(allVariants());
    QString msg = view->toString();
    if (msg.isEmpty()) {
        tSystemError("Mail Message Empty: template name:%s", qPrintable(templateName));
        return false;
    }

    TMailMessage mail(msg, Tf::appSettings()->value(Tf::ActionMailerCharacterSet, "UTF-8").toByteArray());

    // Sets SMTP settings
    bool delay = Tf::appSettings()->value(Tf::ActionMailerDelayedDelivery, false).toBool();

    QByteArray dm = Tf::appSettings()->value(Tf::ActionMailerDeliveryMethod).toByteArray().toLower();
    if (dm == "smtp") {
        // SMTP
        TSmtpMailer *mailer = new TSmtpMailer;
        mailer->setHostName(Tf::appSettings()->value(Tf::ActionMailerSmtpHostName).toByteArray());
        mailer->setPort(Tf::appSettings()->value(Tf::ActionMailerSmtpPort).toUInt());
        mailer->setAuthenticationEnabled(Tf::appSettings()->value(Tf::ActionMailerSmtpAuthentication).toBool());
        mailer->setUserName(Tf::appSettings()->value(Tf::ActionMailerSmtpUserName).toByteArray());
        mailer->setPassword(Tf::appSettings()->value(Tf::ActionMailerSmtpPassword).toByteArray());
        tSystemDebug("%s", mail.toByteArray().data());

        // POP before SMTP
        if ( Tf::appSettings()->value(Tf::ActionMailerSmtpEnablePopBeforeSmtp, false).toBool() ) {
            QByteArray popSvr = Tf::appSettings()->value(Tf::ActionMailerSmtpPopServerHostName).toByteArray();
            quint16 popPort = Tf::appSettings()->value(Tf::ActionMailerSmtpPopServerPort).toInt();
            bool apop = Tf::appSettings()->value(Tf::ActionMailerSmtpPopServerEnableApop, false).toBool();

            mailer->setPopBeforeSmtpAuthEnabled(popSvr, popPort, apop, true);
        }

        // Sends email
        if (delay) {
            mailer->sendLater(mail);
        } else {
            mailer->send(mail);
            mailer->deleteLater();
        }

    } else if (dm == "sendmail") {
        // Command location of 'sendmail'
        QString cmd = Tf::appSettings()->value(Tf::ActionMailerSendmailCommandLocation).toString().trimmed();
        if (cmd.isEmpty()) {
            cmd = Tf::appSettings()->value(Tf::ActionMailerSendmailCommandLocation).toString().trimmed();
        }

        if (!cmd.isEmpty()) {
            TSendmailMailer *mailer = new TSendmailMailer(cmd);
            QByteArray rawmail = mail.toByteArray();
            QList<QByteArray> recipients = mail.recipients();

            if (delay) {
                mailer->sendLater(mail);
            } else {
                mailer->send(mail);
                mailer->deleteLater();
            }
        }

    } else if (dm.isEmpty()) {
        // not send
    } else {
        // Bad parameter
        tSystemError("SMTP: Bad Parameter: ActionMailer.DeliveryMethod: %s", dm.data());
        return false;
    }
    return true;
}