
var kg = require('./kg'),
    moment = require('moment'),
    IMAPHOST = "mail.ayanova.com",
    IMAPPORT = 993,
    IMAPOPTIONS = {
        useSecureTransport: true,
        auth: {
            user: 'support@ayanova.com',
            pass: 'RLdUP6758a6191H'
        },
        id: { name: 'Rockfish', version: '1.x' }
    },
    SMTPHOST = "smtp.ayanova.com",
    SMTPPORT = 465,
    SMTPOPTIONS = {
        useSecureTransport: true,
        name: 'Rockfish',
        auth: {
            user: 'support@ayanova.com',
            pass: 'RLdUP6758a6191H'
        }
    },
    ImapClient = require('emailjs-imap-client'),
    SMTPClient = require('emailjs-smtp-client'),
    requests,
    fetchRequests,
    mailErrorHandler,
    generate_from_request,
    getMessage,
    sendMessage,
    flagMessage,
    cleanMessage,
    makeRequestKey;


/////////////////////////////////////////////////////
// Get requests exported route
//
requests = function (req, callback) {
    return fetchRequests(callback);
    //callback(result);
}


/////////////////////////////////////////////////////
// gracefully handle error without fucking up mail server
//
mailErrorHandler = function (errRetObj, client, callback) {
    callback(errRetObj);
    client.close();
    delete process.env.NODE_TLS_REJECT_UNAUTHORIZED;
}

/////////////////////////////////////////////////////
// internal request fetching
//
fetchRequests = function (callback) {


    var client = new ImapClient(IMAPHOST, IMAPPORT, IMAPOPTIONS);

    client.onerror = function (error) {
        return {
            error: 1,
            msg: 'Error @ key-requests->fetchRequests->onError (some kind of IMAP related error, see error_detail)',
            error_detail: error
        }

    }

    //DANGER DANGER DANGER
    //this is necessary temporarily due to our cert not being valid for some reason
    process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";

    client.connect().then(() => {

        var searchTerms = { UNANSWERED: true, UNDELETED: true, TEXT: 'noreply@ayanova.com', header: ['subject', 'Request for 30 day temporary'] };
        client.search('INBOX', searchTerms, { byUid: true }).then((result) => {
            var ids = '';
            result.forEach((uid) => {
                if (ids) {
                    ids += ',';
                }
                ids += uid;
            });

            if (!ids) {
                client.logout();
                client.close();
                return callback({
                    ok: 1,
                    requests: []
                })
            }

            //imap summary https://www.skytale.net/blog/archives/23-Manual-IMAP.html           
            client.listMessages('INBOX', ids, ["uid", "envelope"], { byUid: true }).then((messages) => {
                //how to iterate the messages in case need to process them here further in future
                // messages.forEach((message) =>
                //     console.log('Message ' + message.uid + ': ' + message.envelope)
                // );
                client.logout();
                client.close();
                return callback({
                    ok: 1,
                    requests: messages
                })
            }, (err) => {

                return mailErrorHandler({
                    error: 1,
                    msg: 'Error @ key-requests->fetchRequests->client.listMessages',
                    error_detail: { code: err.code, message: err.message, stack: err.stack }
                }, client, callback);

            });
        });
    });




}//end of fetchrequests


/////////////////////////////////////////////////////
// get a message for processing
//
getMessage = function (uid, callback) {

    var client = new ImapClient(IMAPHOST, IMAPPORT, IMAPOPTIONS);

    client.onerror = function (error) {
        return {
            error: 1,
            msg: 'Error @ key-requests->fetchRequests->onError (some kind of IMAP related error, see error_detail)',
            error_detail: error
        }

    }

    //DANGER DANGER DANGER
    //this is necessary temporarily due to our cert not being valid for some reason
    process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";

    client.connect().then(() => {



        client.listMessages('INBOX', uid, ["uid", "envelope", "body.peek[text]"], { byUid: true }).then((messages) => {
            //how to iterate the messages in case need to process them here further in future
            // messages.forEach((message) =>
            //     console.log('Message ' + message.uid + ': ' + message.envelope)
            // );
            client.logout();
            client.close();
            if (messages.length < 1) {
                return callback({
                    ok: 1,
                    message: null
                })
            } else {
                return callback({
                    ok: 1,
                    message: messages[0]
                })
            }

        }, (err) => {

            return mailErrorHandler({
                error: 1,
                msg: 'Error @ key-requests->fetchRequests->client.listMessages',
                error_detail: { code: err.code, message: err.message, stack: err.stack }
            }, client, callback);

        });

    });
}//end of getMessage

//////////////////////////////////////////////////
// Get requests exported route
//
generate_from_request = function (req, callback) {

    return getMessage(
        req.params.uid,
        function (message) {
            if (!message.message) {
                return callback({
                    ok: 0,
                    uid: '',
                    keycode: 'Message not found',
                    greeting: 'Message not found',
                    request: 'Message not found'
                })
            } else {

                //generate key from request
                var li = makeRequestKey(req, message);
                //SIGN the license
                var license = kg.signKey(li.parsed);

                //generate the message and callback with it
                kg.msgGen(li, license, function (genObj) {
                    return callback({
                        ok: 1,
                        uid: req.params.uid,
                        requestReplyToAddress: li.requestReplyToAddress,
                        requestFromReplySubject: li.requestFromReplySubject,
                        requestKeyIsLite: li.isLite,
                        keycode: genObj.keyMessage,
                        greeting: genObj.requestGreeting,
                        request: li.requestMessage
                    }
                    );
                });
            }
        }
    );
}


///////////////////////////////////
// MAKE A KEY FROM REQUEST MESSAGE
makeRequestKey = function (req, message) {

    var s = cleanMessage(message.message['body[text]']);
    var bLite = message.message.envelope.subject.includes('AyaNova Lite');
    var nNameStart = s.indexOf("Name:\n") + 6;
    var nNameEnd = s.indexOf("Company:\n");
    var nCompanyStart = nNameEnd + 9;
    var nCompanyEnd = s.indexOf("Referrer:\n");
    var sName = s.substring(nNameStart, nNameEnd - 1).trim();
    if (sName.includes(" ")) {
        sName = sName.split(' ')[0];
    }
    var sRegTo = s.substring(nCompanyStart, nCompanyEnd - 1).trim();

    var keyType = 'AyaNovaLicenseKey';
    if (bLite == true) {
        keyType = 'AyaNovaLiteLicenseKey';
    }


    var li = {};
    li[keyType] = {};
    li[keyType].SchemaVersion = '7';


    //Hex encode the source to obscure it from users
    var buffer = new Buffer('Rockfish - IP: ' + req.ip + ' USER: ' + req.apitoken.id);
    li[keyType].Source = buffer.toString('hex');

    //c# version of id
    //Math.Truncate((DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
    var rightNow = new Date();
    var oneMonthISOString = createDateAsUTC(moment().add(1, 'M').toDate()).toISOString();
    li[keyType].Id = Math.floor(Date.now() / 1000).toString();
    li[keyType].Created = createDateAsUTC(rightNow).toISOString();// new Date(Date.UTC(rightNow.getUTCFullYear(), rightNow.getUTCMonth(), rightNow.getUTCDate(),0,0,0)).toISOString();
    li[keyType].Sub = 'true';
    li[keyType].RegisteredTo = sRegTo;
    li[keyType].InstallableUntil = oneMonthISOString;
    if (bLite) {
        li[keyType].TotalScheduleableUsers = '1';
    } else {
        li[keyType].TotalScheduleableUsers = '5';
    }

    li[keyType].Expires = oneMonthISOString;
    li[keyType].RequestedTrial = 'true';


    li[keyType].Plugins = {
        Plugin: []
    };

    //ADD TRIAL PLUGINS
    li[keyType].Plugins.Plugin.push({
        Item: 'QBI - QuickBooks interface',
        SubscriptionExpires: oneMonthISOString
    });

    li[keyType].Plugins.Plugin.push({
        Item: 'PTI - US Sage 50/Peachtree interface',
        SubscriptionExpires: oneMonthISOString
    });

    li[keyType].Plugins.Plugin.push({
        Item: 'ExportToXls',
        SubscriptionExpires: oneMonthISOString
    });

    li[keyType].Plugins.Plugin.push({
        Item: 'OutlookSchedule',
        SubscriptionExpires: oneMonthISOString
    });

    li[keyType].Plugins.Plugin.push({
        Item: 'AyaNovaOLI',
        SubscriptionExpires: oneMonthISOString
    });

    li[keyType].Plugins.Plugin.push({
        Item: 'ImportExportCSVDuplicate',
        SubscriptionExpires: oneMonthISOString
    });

    if (!bLite) {

        li[keyType].Plugins.Plugin.push({
            Item: 'QuickNotification',
            SubscriptionExpires: oneMonthISOString
        });

        li[keyType].Plugins.Plugin.push({
            Item: 'MBI - Minimal browser interface',
            SubscriptionExpires: oneMonthISOString
        });

        li[keyType].Plugins.Plugin.push({
            Item: 'WBI - Web browser interface',
            SubscriptionExpires: oneMonthISOString
        });

        li[keyType].Plugins.Plugin.push({
            Item: 'RI - Responsive Interface',
            SubscriptionExpires: oneMonthISOString
        });
    }

    var replyTo = message.message.envelope['reply-to'][0].address;

    return {
        keyType: keyType,
        licenseType: 'webRequestedTrial',
        isLite: bLite,
        keyWillLockout: false,
        requestMessage: s,
        greetingName: sName,
        requestReplyToAddress: replyTo,
        requestFromReplySubject: 're: ' + message.message.envelope.subject,
        parsed: li
    };

}


///////////////////////////////////////////////////////
// RETURN A DATE AS UTC WITH SAME d/m/y as passed date
// strips out time
//
createDateAsUTC = function (date) {
    return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0));
}


//////////////////////////
// CLEAN WEIRD ENCODING IN MESSAGE 
//
cleanMessage = function (m) {
    if (!m) {
        return '';
    } else {
        //Strip out soft linebreaks and extra ones and change encoded crlf to newlines
        return m.replace(/=\r/g, '').replace(/=\n/g, '').replace(/\r/g, '').replace(/\n/g, '').replace(/=0D=0A/g, '\n');
    }
}


//////////////////////////////////////////////////
// Email submitted response
//
email_response = function (req, callback) {
    var r = req.body;

    //send the greeting message first
    sendMessage(r.requestReplyToAddress, r.requestFromReplySubject, r.greeting, function (ret) {
        if (ret.error) {
            return callback(ret);
        } else {

            //send the keycode
            var keyEmailSubject = '';
            if (r.requestKeyIsLite) {
                keyEmailSubject = "AyaNova Lite and optional add-ons temporary 30 day Activation key";
            }
            else {
                keyEmailSubject = "AyaNova and optional add-on's temporary 30 day Activation key";
            }

            sendMessage(r.requestReplyToAddress, keyEmailSubject, r.keycode, function (ret2) {
                if (ret2.error) {
                    return callback(ret2);
                } else {
                    flagMessage(r.uid, function (ret3) {
                        return callback(ret3)
                    })
                }
            })

        }
    })
}


//////////////////////////////////////////////////
// SEND email
//
sendMessage = function (msgto, msgsubject, msgbody, callback) {

    var smtpclient = new SMTPClient(SMTPHOST, SMTPPORT, SMTPOPTIONS)

    // run only once as 'idle' is emitted again after message delivery
    var alreadySending = false;

    smtpclient.onidle = function () {
        if (alreadySending) {
            return;
        }
        console.log(">>> onidle, connection established (" + msgsubject + ") <<<<<<<");
        alreadySending = true;
        smtpclient.useEnvelope({
            from: "support@ayanova.com",
            to: [msgto]
        });
    }

    smtpclient.onready = function () {
        console.log(">>> SENDING: " + msgsubject + " <<<<<<<");
        smtpclient.send("Subject:" + msgsubject + "\r\n");
        smtpclient.send("From: support@ayanova.com\r\n");
        smtpclient.send("To: " + msgto + "\r\n")
        smtpclient.send("\r\n");
        smtpclient.send("\r\n");
        smtpclient.send(msgbody);
        smtpclient.end();
    }

    smtpclient.ondone = function (success) {
        smtpclient.quit();
        console.log(">>> ondone: " + success + " (" + msgsubject + ") <<<<<<<");
        return callback({
            ok: 1,
            result: success
        });
    }

    smtpclient.onerror = function (err) {
        smtpclient.quit();
        console.log(">>> ondone: " + err + " (" + msgsubject + ") <<<<<<<")
        return callback({
            error: 1,
            msg: "key-requests::sendMessage-> Error sending see error_detail",
            error_detail: err
        });
    }

    //trigger the whole thing
    smtpclient.connect();
}


/////////////////////////////////////////////////////
// Flag original request message as read and replied
//
flagMessage = function (uid, callback) {

    var client = new ImapClient(IMAPHOST, IMAPPORT, IMAPOPTIONS);

    client.onerror = function (error) {
        return {
            error: 1,
            msg: 'Error @ key-requests->flagMessage->onError (some kind of IMAP related error, see error_detail)',
            error_detail: error
        }

    }

    //DANGER DANGER DANGER
    //this is necessary temporarily due to our cert not being valid for some reason
    process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";

    client.connect().then(() => {


        //flag as read and replied (seen, answered)
        client.setFlags('INBOX', uid, { set: ['\\Seen', '\\Answered'] }, { byUid: true }).then((messages) => {
            //how to iterate the messages in case need to process them here further in future
            // messages.forEach((message) =>
            //     console.log('Message ' + message.uid + ': ' + message.envelope)
            // );
            client.logout();
            client.close();
            if (messages.length < 1) {
                return callback({
                    ok: 1,
                    message: null
                })
            } else {
                return callback({
                    ok: 1,
                    message: messages[0]
                })
            }

        }, (err) => {

            return mailErrorHandler({
                error: 1,
                msg: 'Error @ key-requests->fetchRequests->client.listMessages',
                error_detail: { code: err.code, message: err.message, stack: err.stack }
            }, client, callback);

        });

    });
}//end of flagMessage






//------------------------------------------------
module.exports = {
    requests: requests,
    generate_from_request: generate_from_request,
    email_response: email_response
};

