'use strict';

var sharedUrl = require('../../shared/SharedUrlRoutes');
var EmailConfig;
var EmailHelper = {};

var Email = require('email-templates');
var path = require('path');
var handlebars = require('handlebars');
const fs = require('fs-extra');
const sgMail = require('@sendgrid/mail');
var baseUrlPath;

let email;
let templateFile = '';

const setUpTemplates = async () => {
    if (!email) {
        const vendorPath = path.join(__dirname, '../private/vendor/email-templates');
    
        let root = path.join(__dirname, 'email-templates'); 
        const exists = await fs.pathExists(vendorPath);
        if (exists) {
            root = vendorPath;
            templateFile = '/html.hbs';
        }

        email = new Email({
            views: {
                root,
                options: { extension: 'hbs' }
            },
            transport: {
                jsonTransport: true
            }
        });
    }

    return email;
};


module.exports = EmailHelper;

const isEmailJS = () => !!EmailHelper.server;

const send = (msg, callback) => {
    if (isEmailJS()) {
        EmailHelper.server.send(msg, callback);
    } else {
        sgMail.send(msg).then(result => {
            callback(null, result);
        }).catch((error) => {
            callback(error);
        });
    }
};

function setupServer() {
    EmailConfig = config.get('email');
    if (!EmailConfig) {
        throw new Error('Email settings not configured. Emailing functions will not be available.');
    }
    
    if (EmailConfig.sgApiKey) {
        sgMail.setApiKey(EmailConfig.sgApiKey);
    } else {
        EmailHelper.server = require("emailjs/email").server.connect(EmailConfig);
    }
}

function buildUrl(fullDomainUrl, link) {
    if (!baseUrlPath) {
        baseUrlPath = require("../web/BaseURLPath");
    }

    if (baseUrlPath.basePath === "") {
        return fullDomainUrl + "/" + link;
    }

    return fullDomainUrl + "/" + baseUrlPath.basePath + "/" + link;
}

EmailHelper.dispatchActivateAccountLink = function (account, fullDomainUrl, callback) {
    try {
        setupServer();
    }catch (err) {
        callback(err);
        return;
    }

    logger.debug("Dispatching account creation email to " + account.email + " with url " + fullDomainUrl);
    EmailHelper.composeActivateEmail(account, fullDomainUrl, function (results) {
        const options = {
            from: EmailConfig.sender,
            to: account.email,
            subject: 'Activate Account',
            text: 'Please activate your account'
        };

        if (isEmailJS()) {
            options.attachment = {data: results.html.toString(), alternative: true};
        } else {
            options.html = results.html.toString();
        }

        send(options, callback);
    });
};

EmailHelper.composeActivateEmail = function (o, fullDomainUrl, callback) {

    handlebars.registerPartial('email', '{{email}}');
    handlebars.registerPartial('link', '{{link}}');

    var link = buildUrl(fullDomainUrl, sharedUrl.serverRoutes.appActivateAccount + '?token=' + o.token);
    var dataPartial = {link: link };

    setUpTemplates()
        .then(email => {
            return email.render('email-activation' + templateFile, dataPartial);
        }).then(result => {
            // return result under html, old rules/components may still use it like results.html.toString()
            callback({ html: result }); 
        }).catch(err => {
            logger.error("Error on composeActivateEmail: " + err);
            callback(null);
        });
};

EmailHelper.dispatchResetPasswordLink = function (account, fullDomainUrl, callback) {
    try {
        setupServer();
    }catch (err) {
        callback(err);
        return;
    }

    EmailHelper.composeResetPassEmail(account, fullDomainUrl, function (results) {
        const options = {
            from: EmailConfig.sender,
            to: account.email,
            subject: 'Reset Password',
            text: 'Reset password request received'
        };

        if (isEmailJS()) {
            options.attachment = {data: results.html.toString(), alternative: true};
        } else {
            options.html = results.html.toString();
        }

        send(options, callback);
    });
};

EmailHelper.composeResetPassEmail = function (o, fullDomainUrl, callback) {
    var link = buildUrl(fullDomainUrl, sharedUrl.serverRoutes.appResetPass + '?e=' + o.email + '&p=' + o.pass);

    handlebars.registerPartial('email', '{{email}}');
    handlebars.registerPartial('link', '{{link}}');
    var dataPartial = {email: o.email, link: link};

    setUpTemplates()
        .then(email => {
            return email.render('email-reset-pass' + templateFile, dataPartial);
        }).then(result => {
            // return result under html, old rules/components may still use it like results.html.toString()
            callback({ html: result });
        }).catch(err => {
            logger.error("Error on composeResetPassEmail: " + err);
            callback(null);
        });
};

EmailHelper.sendMail = function (to, subject, content, callback) {
    try {
        setupServer();
    }catch (err) {
        callback(err);
        return;
    }

    send({
        from: EmailConfig.sender,
        to: to,
        subject: subject,
        text: content
    }, callback);
};

EmailHelper.sendHtmlMail = function (from, to, cc, bcc, subject, text, htmlContent, attachments, callback) {
    try {
        setupServer();
    }catch (err) {
        callback(err);
        return;
    }

    var sender = from ? from : EmailConfig.sender;
    logger.info("Sending email to : " + to + " with subject " + subject);

    const options = {
        from: sender,
        to: to,
        cc: cc,
        bcc: bcc,
        subject: subject,
        text: text
    }; 

    if (isEmailJS()) {
        var attach = [
            {data: htmlContent, alternative: true}
        ];

        if (attachments) {
            attach = attach.concat(attachments);
        }

        options.attachment = attach;
    } else {
        options.html = htmlContent;
        options.attachments = attachments || [];
    }

    send(options, callback);
};
