/**
 * tizen_common.js
 * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
 *
 * Contact:
 * DongHee Yang <donghee.yang@samsung.com>
 * Sungmin Kim <sm.art.kim@samsung.com>
 * Jiil Hyoun <jiil.hyoun@samsung.com>
 * Jonghwan Park <iwin100.park@samsung.com>
 * Kitae Kim <kt920.kim@samsung.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Contributors:
 * - S-Core Co., Ltd
**/

var _ = require('underscore');
var async = require('async');
var path = require('path');

var TizenGit = require('../org.tizen.projects/git-control.js');
var Package = require('./package.js');
var Snapshot = require('../org.tizen.repository/snapshot.js');
var RemoteRepo = require('../org.tizen.repository/remote-repo.js');
var dibs = require('../../core/dibs.js');
var DError = require('../../core/exception.js');
var JobDep = require('../org.tizen.projects/job-dep.js');
var utils = require('../../lib/utils.js');

/**
 * check changlog information
 * only check whether changelog is right
 * 1. change log version duplicate check
 * 2. package version and change log version diff check
 * @public
 * @function checkChangelog
 * @param {Array} pkgList - package list from pkginfo.manifest file
 * @param {Array} changelogList - changelog list from changelog file
 * @param callack - callback (error)
 * @memberOf module:models/tizen-common/tizen_common
 */

module.exports.checkChangelog = function checkChangelog(pkgList, changelogList, callback) {
    async.waterfall([
        // duplicated version check
        function (wcb) {
            changelogList = _.compact(changelogList);
            var rawVersionList = _.map(changelogList, function (changelog) {
                return changelog.version;
            });
            var dupList = _.select(rawVersionList, function (version) {
                return (_.indexOf(rawVersionList, version) !== _.lastIndexOf(rawVersionList, version));
            });
            if (_.size(dupList) !== 0) {
                var error = new Error('Changelog version ' + dupList.join('/') + ' is duplicated!');
                wcb(error, null);
            } else {
                wcb(null, changelogList);
            }
        },
        // package version check
        function (changelogList, wcb) {
            var changelogVersion = _.map(changelogList, function (log) {
                return log.version;
            })[0];
            if (pkgList[0].version === changelogVersion) {
                wcb(null);
            } else {
                var error = new Error('package version : [' + pkgList[0].version + '] is not same as changelog version : [' + changelogVersion + ']');
                wcb(error);
            }
        }
    ], function (err) {
        callback(err);
    });
};


/**
 * logs saving method
 * it expect to avoid db string length limit
 * process
 * 1. save logs length as count
 * 2. save each log with log index
 * if empty logs in then job never changed
 * @public
 * @function setDBLogs
 * @param {Array} job - owner of logs
 * @param {Array} logs - log list
 * @param {Array} type - prefix of each log ( ex COMMIT_LOG, CHANGE_LOG )
 * @param callack - callback (error)
 * @memberOf module:models/tizen-common/tizen_common
 */
function setDBLogs(job, logs, type) {
    logs = _.compact(logs);
    if (logs.length > 0) {
        job.options[type + '_COUNT'] = logs.length;
        _.each(logs, function (log, idx) {
            job.options[type + '_' + idx] = log;
        });
    }
}

/**
 * get attribute from last build info
 * require
 * 1. when Tizen-Binary project must be setted snapshot in job
 * @public
 * @function getLatestAttribute
 * @param {Array} job - job object
 * @param {Array} attr - search field name
 * (ex Tizen-Source : version, gitRepo, gitCommit, packageNames)
 * (ex Tizen-Binary : package's all attributes)
 * @param callack - callback (error)
 * @memberOf module:models/tizen-common/tizen_common
 */
function getLatestAttribute(job, attr) {
    switch (job.type) {
    case 'Tizen-Source' :
        if (job.options.LAST_BUILD_INFO && job.options.LAST_BUILD_INFO[job.options.TARGET_OS] &&
            job.options.LAST_BUILD_INFO[job.options.TARGET_OS][attr]) {
            return job.options.LAST_BUILD_INFO[job.options.TARGET_OS][attr];
        } else {
            return;
        }
    case 'Tizen-Binary' :
        if (job.snapshot) {
            return Snapshot.getPackage(job.snapshot, job.options.packages[0].name, job.options.packages[0].os)[attr];
        } else {
            return;
        }
    default:
        return;
    }
}

module.exports.set_changelog_to_jobinfo = function set_changelog_to_jobinfo(job, changelogList, callback) {
    if (job.options.packages[0].version) {
        var pkgVersion = job.options.packages[0].version;
        var selectedList = [];
        var lastVersion = getLatestAttribute(job, 'version');
        // latest version exist
        if (lastVersion) {
            selectedList = _.select(changelogList,
                function (log) {
                    return Package.compareVersion(log.version, lastVersion) > 0;
                }
            );
            setDBLogs(job, selectedList, 'CHANGE_LOG');
        }
        // first change log check
        else {
            var pkgLog = _.detect(changelogList,
                function (log) {
                    return log.version === pkgVersion;
                }
            );
            setDBLogs(job, [pkgLog], 'CHANGE_LOG');
        }
    }
    callback(null);
};

module.exports.set_commit_to_jobinfo = function set_commit_to_jobinfo(job, srcPath, callback) {
    var lastCommitId = getLatestAttribute(job, 'gitCommit');
    if (lastCommitId) {
        TizenGit.getLog(srcPath, lastCommitId, '',
            function (err, logs) {
                // if LAST BUILD INFO is ruined
                if (err) {
                    TizenGit.getLog(srcPath, '-1', '',
                        function (err2, logs2) {
                            if (!err2) {
                                setDBLogs(job, [logs2[0]], 'COMMIT_LOG');
                            }
                        });
                    callback(null);
                } else {
                    // right COMMIT DIFF
                    setDBLogs(job, logs, 'COMMIT_LOG');
                    callback(null);
                }
            });
    } else {
        // new COMMIT LOG
        TizenGit.getLog(srcPath, '-1', '',
            function (err, logs) {
                if (!err) {
                    setDBLogs(job, [logs[0]], 'COMMIT_LOG');
                }
                callback(null);
            }
        );
    }
};

/**
 * simple upload process
 * process
 * 1. get repo server
 * 2. register local files to repo server
 * @public
 * @function upload
 * @param {String} uploadFiles - local file list to upload
 * @param {String} distName - distribution name
 * @param {Boolean} compat - set uploadCompat option of repo.registerRemotePackages
 * @param {Boolean} force - set forceupload option of repo.registerRemotePackages
 * @param {String} userEmail - set userEmail as uploader
 * @param {Boolean} isTemp - temp upload option of repo.registerRemotePackages
 * @param {String} jobId - when temp upload using jobId for temp dir
 * @param callack - callback (error, snapshotInfo)
 * @memberOf module:models/tizen-common/tizen_common
 */
// callback(err, snapshotInfo)
module.exports.upload = upload;
function upload(uploadFiles, distName, compat, force, userEmail, isTemp, jobId, buildInfo, monitor, callback) {
    var temp = isTemp ? true : false;
    if (temp) {
        monitor.updateProgress('Upload result files to temporary repository...');
    } else {
        monitor.updateProgress('Uploading...');
    }
    monitor.updateProgress(' - [' + uploadFiles.map(function (e) {
        return path.basename(e);
    }).join(',') + ']');


    // get repo server
    var repoServers = dibs.getServersByType('repo');
    if (repoServers.length === 0) {
        var error = new DError('TIZENGITJOB007');
        callback(error, null);
        return;
    }

    // register files
    repoServers[0].registerRemotePackages(uploadFiles, {
        repoType: 'tizen',
        distName: distName,
        uploadCompat: compat ? true : false,
        forceUpload: (force || temp) ? true : false,
        userEmail: userEmail,
        isTemp: temp,
        tempJobId: jobId ? jobId : null,
        buildInfo: buildInfo,
        progress: function (msg) {
            monitor.updateProgress(' - ' + msg);
        }
    }, function (err, snapshotInfo) {
        if (!err) {
            monitor.updateProgress(' - uploading package succeeded! ');
        } else {
            monitor.updateProgress({
                log: ' - uploading package failed! ',
                logType: 'error'
            });
        }
        callback(err, snapshotInfo);
    });
}

/**
 * upload Tizen packages process form job
 * process
 * 1. setting job.board
 * 2. upload
 * 3. setting job.snapshotName
 * 4. settring job.board
 * @public
 * @function upload
 * @param {object} job - job object that must include below
 *                      { id : string,
 *                        resultFiles : [string...],
 *                        userEmail : string}
 * @param {object} monitor - monitor object
 * @param callack - callback (error)
 * @memberOf module:models/tizen-common/tizen_common
 */
// callback(err)
module.exports.uploadJobPackages = uploadJobPackages;
function uploadJobPackages(job, tempUpload, monitor, callback) {
    if (job.board) {
        job.board.push({
            type: 'STAMP',
            time: utils.getTimeString(),
            name: 'upload'
        });
    }
    upload(job.resultFiles,
        job.distName,
        job.options.UPLOAD_COMPAT,
        job.options.FORCE_REBUILD,
        job.userEmail,
        tempUpload,
        job.id,
        job.buildInfo || null,
        monitor,
        function (err, snapshotInfo) {
            if (!err) {
                job.snapshotName = snapshotInfo.name;
                monitor.updateProgress('Snapshot published...' + job.snapshotName);

                if (job.board) {
                    job.board.push({
                        type: 'STAMP',
                        time: utils.getTimeString(),
                        name: 'upload done'
                    });
                }
            }
            callback(err, job);
        });
}


// src dep / build dep / install dep list except self
module.exports.getDepList = function getDepList(packages) {
    var depList = [];
    _.each(packages, function (pkg) {
        if (pkg.buildDepList) {
            depList = depList.concat(pkg.buildDepList);
        }
        if (pkg.installDepList) {
            depList = depList.concat(pkg.installDepList);
        }
        if (pkg.srcDepList) {
            depList = depList.concat(pkg.srcDepList);
        }
    });

    var selfsupplyList = [];
    _.each(packages, function (pkg) {
        selfsupplyList = _.union(selfsupplyList, _.select(depList, function (dep) {
            return (dep.packageName === pkg.name && pkg.osList.indexOf(dep.os) > -1);
        }));
    });
    return _.difference(depList, selfsupplyList);
};


module.exports.checkDependencyExistInRepo = function checkDependencyExistInRepo(job, callback) {
    var dist = null;
    async.waterfall([
        // search distribution
        function (wcb) {
            if (job.distribution) {
                dist = job.distribution;
                wcb(null);
            } else {
                dibs.rpc.datamgr.searchDistributions({
                    name: job.distName
                }, function (err, dists) {
                    if (!err && dists.length > 0) {
                        dist = dists[0];
                    }
                    wcb(err);
                });
            }
        },
        // get snapshots
        function (wcb) {
            dibs.rpc.repo.searchSnapshots({
                name: null,
                repoType: 'tizen',
                distName: job.distName
            }, wcb);
        },
        // set snapshots for furder work
        function (snapshots, wcb) {
            if (snapshots.length > 0) {
                job.snapshot = snapshots[0];
                job.snapshot.distName = job.distName;
                wcb(null);
            } else {
                if (dist && dist.options.PARENT_REPO_URL) {
                    wcb(null);
                } else {
                    wcb(new Error('repository tizen:' + job.distName + ' has no snapshots'));
                }
            }
        },
        // check dependencies
        function (wcb) {
            async.select(job.depList, function (dep, acb) {
                if (job.snapshot && job.snapshot.osPackages &&
                    job.snapshot.osPackages[dep.os] &&
                    job.snapshot.osPackages[dep.os][dep.packageName]) {
                    acb(false);
                } else if (job.snapshot && job.snapshot.archivePackages &&
                    _.indexOf(job.snapshot.archivePackages, dep.packageName) > -1) {
                    acb(false);
                } else {
                    acb(true);
                }
            }, function (results) {
                if (results.length === 0) {
                    wcb(null);
                } else {
                    if (dist && dist.options.PARENT_REPO_URL) {
                        checkDependencyInParentRepo(job.id, results, dist.options.PARENT_REPO_URL, wcb);
                    } else {
                        wcb(new Error('unmet dependency of multi Job #' + job.id + ' :' +
                            _.uniq(_.map(results, function (dep) {
                                return dep.packageName + '(' + dep.os + ')';
                            }))));
                    }
                }
            });
        }
    ], function (err) {
        callback(err);
    });
};


function checkDependencyInParentRepo(jobId, depList, parentRepoURL, callback) {
    var parentServerURL = path.dirname(parentRepoURL);
    var parentDistName = path.basename(parentRepoURL);
    var snapshot = null;
    var parentRepo = RemoteRepo.createRemoteRepo(parentServerURL, {
        distName: parentDistName,
        snapshotName: null
    });
    async.series([
        function (cb) {
            parentRepo.open(null, cb);
        },
        function (cb) {
            parentRepo.searchSnapshots({
                name: null,
                repoType: 'tizen',
                distName: parentDistName
            }, function (err, snapshots) {
                if (!err && snapshots.length > 0) {
                    snapshot = snapshots[0];
                    snapshot.distName = parentDistName;
                }
                cb(err);
            });
        },
        function (cb) {
            async.select(depList, function (dep, acb) {
                if (snapshot && snapshot.osPackages &&
                    snapshot.osPackages[dep.os] && snapshot.osPackages[dep.os][dep.packageName]) {
                    acb(false);
                } else if (snapshot && snapshot.archivePackages &&
                    _.indexOf(snapshot.archivePackages, dep.packageName) > -1) {
                    acb(false);
                } else {
                    acb(true);
                }
            }, function (results) {
                if (results.length === 0) {
                    cb(null);
                } else {
                    cb(new Error('unmet dependency of multi Job #' + jobId + ' :' +
                        _.uniq(_.map(results, function (dep) {
                            return dep.packageName + '(' + dep.os + ')';
                        }))));
                }
            });
        }
    ], function (err) {
        callback(err);
    });
}


module.exports.checkMutualExclusiveJob = function checkMutualExclusiveJob(srcJob, tarJob) {
    if (srcJob.distName !== tarJob.distName) {
        return false;
    }
    if (JobDep.hasSamePackages(srcJob, tarJob) ||
        JobDep.hasBuildDependency(srcJob, tarJob) ||
        JobDep.hasBuildDependency(tarJob, srcJob)) {

        return true;
    }

    return false;
};


module.exports.generateTizenBuildSummary = generateTizenBuildSummary;

function generateTizenBuildSummary(job) {
    var index = '';
    var summary = '';

    summary += ' Distribution: ' + job.distName + '\n\n';
    if (job.projectType === 'Tizen-Multi') {
        var projectNameList = _.uniq(_.pluck(job.subJobs, 'projectName'));
        var subJobs = [];
        projectNameList.forEach(function (projectName) {
            var subJob = _.find(job.subJobs, function (subJob) {
                return subJob.projectName === projectName;
            });
            subJobs.push(subJob);
        });

        summary += _.map(subJobs, function (subJob) {
            var tempSummary = '';
            tempSummary += ' Project Name: ' + subJob.projectName + '\n';
            if (subJob.projectType === 'Tizen-Source') {
                tempSummary += ' Source Information:\n';
                for (var i = 0; i < subJob.options.COMMIT_LOG_COUNT; i++) {
                    index = 'COMMIT_LOG_' + i;
                    tempSummary += '  - Commit: ' + subJob.options[index].Commit + '\n';
                    tempSummary += '  - Author: ' + subJob.options[index].Author + '\n';
                    tempSummary += '  - Date: ' + subJob.options[index].Date + '\n';
                    tempSummary += '  - Contents:\n' + subJob.options[index].Contents + '\n';
                }
            } else if (subJob.projectType === 'Tizen-Binary') {
                if (subJob.options.UPLOAD_COMPAT) {
                    tempSummary += ' Compatible Package Option: enabled\n';
                }
            }
            tempSummary += '\n';
            return tempSummary;
        }).join('\n');
    } else {
        summary += ' Project Name: ' + job.projectName + '\n';
        if (job.projectType === 'Tizen-Source') {
            summary += ' Source Information:\n';
            for (var i = 0; i < job.options.COMMIT_LOG_COUNT; i++) {
                index = 'COMMIT_LOG_' + i;
                summary += '  - Commit: ' + job.options[index].Commit + '\n';
                summary += '  - Author: ' + job.options[index].Author + '\n';
                summary += '  - Date: ' + job.options[index].Date + '\n';
                summary += '  - Contents:\n' + job.options[index].Contents + '\n';
            }
        } else if (job.projectType === 'Tizen-Binary') {
            if (job.options.UPLOAD_COMPAT) {
                summary += ' Compatible Package Option: enabled\n';
            }
        }
    }

    if (job.options.CHANGE_LOG_COUNT) {
        summary += '\n';
        for (var j = 0; j < job.options.CHANGE_LOG_COUNT; j++) {
            index = 'CHANGE_LOG_' + j;
            if (job.options[index]) {
                summary += ' Version: ' + job.options[index].version + '\n';
                summary += job.options[index].contents + '\n';
            }
        }
    }

    if (job.snapshotName) {
        summary += ' Snapshot : ' + job.snapshotName + '\n';
    }

    summary += ' Package(s) Name:\n  ';
    summary += _.map(job.resultFiles, function (file) {
        return file.split(/[/]+/).pop();
    }).join('\n  ');
    summary += '\n';

    return summary;
}

// callback(err)
module.exports.checkApproval = checkApproval;
function checkApproval(approvalId, callback) {

    dibs.rpc.approvalmgr.getApproval(approvalId, function (err, approval) {
        if (err) {
            callback(err);
        } else if (!approval) {
            callback(new DError('TIZENJOB022'));
        } else if (approval.submissionStatus === 'SUBMITTED') { //Already approval process is done
            var approvalmgr = dibs.getServersByType('approvalmgr')[0];

            approvalmgr.addEventListener(
                'APPROVAL_STATUS_CHANGED',
                {
                    approvalId: approvalId
                },
                function (eventObj, eventCb) {
                    switch (eventObj.status) {
                    case 'APPROVED':
                        callback(null);
                        break;
                    case 'REJECTED':
                        callback(new DError('TIZENJOB016'));
                        break;
                    case 'CANCELED':
                        callback(new DError('TIZENJOB021'));
                        break;
                    default:
                        break;
                    }
                    eventCb(null);
                },
                function (err) {
                    if (err) { // is not PENDING
                        callback(err);
                    }
                });
        } else {
            switch (approval.submissionStatus) {
            case 'APPROVED':
                callback(null);
                break;
            case 'REJECTED':
                callback(new DError('TIZENJOB016'));
                break;
            case 'CANCELED':
                callback(new DError('TIZENJOB021'));
                break;
            default:
                callback(new Error('System error- not defined status: ' + approval.submissionStatus));
                break;
            }
        }
    });
}

module.exports.resumeJob = resumeJob;
function resumeJob(jobSvc, job, options, monitor, callback) {
    if (job.status !== 'PENDING') {
        return callback(new Error('cancel'));
    }

    if (!job.approvalId) {
        return callback(new Error('cancel'));
    }

    if (options.error) {
        monitor.updateProgress('Approval is failed: ' + options.error);
        return callback(options.error);
    }

    job.statusInfo = 'Job #' + job.id + ' is approval done.';
    if (job.board) {
        job.board.push({
            type: 'STAMP',
            time: utils.getTimeString(),
            name: 'approval done'
        });
    }

    async.series([
        function (cb) {
            monitor.updateProgress('status change : WORKING');
            jobSvc.updateJobStatus(job, 'WORKING', cb);
        },
        function (cb) {
            if (!job.resultFiles) {
                job.resultFiles = job.options.resultFiles; //for recovery job
            }
            uploadJobPackages(job, false, monitor, cb);
        }
    ], function (err) {
        if (err) {
            monitor.updateProgress('- approval upload failed');
        } else {
            monitor.updateProgress('- approval upload done');
        }
        callback(err);
    });
}

module.exports.pendingJobHandler = pendingJobHandler;
function pendingJobHandler(job, callback) {
    checkApproval(job.approvalId, callback);
}

function approvalProcess(jobSvc, job, monitor, callback) {
    async.waterfall([
        function (cb) {
            monitor.updateProgress('Publishing temp snapshot...');
            uploadJobPackages(job, true, monitor, function (err) {
                cb(err);
            });
        },
        function (cb) {
            monitor.updateProgress('Start approval process...', cb);
        },
        function (cb) {
            if (job.board) {
                job.board.push({
                    type: 'STAMP',
                    time: utils.getTimeString(),
                    name: 'approval'
                });
            }
            var summary = generateTizenBuildSummary(job);
            var subject = '';
            if (job.options.approvalInfo.subject) {
                subject = '[JOB-' + job.id + '] ' + job.options.approvalInfo.subject;
            } else {
                if (job.projectName) {
                    subject = '[JOB-' + job.id + '] ' + job.projectName;
                } else {
                    subject = '[JOB-' + job.id + '] ' + job.subJobs[0].projectName + ' and other ' + (job.subJobs.length - 1) + ' projects';
                }
            }

            // for recovery
            // TODO: remove duplicated information about resultFiles
            job.options.resultFiles = job.resultFiles;

            dibs.rpc.approvalmgr.addApproval(
                job.userEmail,
                subject,
                job.options.approvalInfo.contents,
                summary,
                job.options.approvalInfo.approvalRoutes,
                'PACKAGE_UPLOAD',
                cb);
        },
        function (approval, cb) {
            job.statusInfo = 'Job #' + job.id + ' is under approval.';
            job.approvalId = approval.id;
            monitor.updateProgress('- job status updating PENDING...');
            jobSvc.updateJobStatus(job, 'PENDING', cb);
        }
    ],
    function (err) {
        if (err) {
            monitor.updateProgress('- approval process failed');
        } else {
            monitor.updateProgress('Job #' + job.id + ' is under approval.');
        }
        callback(err, job);
    });
}

//callback(err)
module.exports.binaryUploadApprovalProcess = binaryUploadApprovalProcess;
function binaryUploadApprovalProcess(jobSvc, job, monitor, callback) {
    if (job.options.BUILD_ONLY) {
        monitor.updateProgress(' - skipped uploading by BUILD_ONLY option');
        callback(null, job);
    } else if (job.options.UPLOAD_TEMP && job.parentId === null) {
        uploadJobPackages(job, true, monitor, callback);
    } else if (job.options.UPLOAD && job.options.approvalInfo) {
        approvalProcess(jobSvc, job, monitor, callback);
    } else if (job.options.UPLOAD) {
        uploadJobPackages(job, false, monitor, callback);
    } else {
        monitor.updateProgress(' - skipped uploading');
        callback(null, job);
    }
}

//callback(err)
function statusChange(job, status) {
    job.status = status;
    stripTizenJob(job);

    dibs.thisServer.emitEvent({
        event: 'JOB_STATUS_CHANGED',
        status: status,
        jobId: job.id,
        job: job
    });
}


module.exports.checkReleasePhase = checkReleasePhase;
//callback(err, job)
function checkReleasePhase(job, callback) {
    if (job.parentId && job.options.approvalInfo) {
        callback(new DError('TIZENJOB019', {
            parentId: job.parentId
        }), job);
    } else if (!(job.options.UPLOAD) && job.options.approvalInfo) {
        callback(new DError('TIZENJOB020', {}), job);
    } else {
        async.waterfall([
            function (cb) {
                dibs.rpc.datamgr.searchDistributions({
                    name: job.distName
                }, cb);
            },
            function (dist, cb) {
                var error = null;
                if (dist[0].options.PHASE === 'release') { // approvalInfo must have
                    if (!job.options.approvalInfo && !job.parentId && job.options.UPLOAD) {
                        error = new DError('TIZENJOB018', {
                            distName: job.distName
                        });
                    }
                    if (job.options.approvalInfo && (!job.options.approvalInfo.approvalRoutes ||
                        _.isEmpty(job.options.approvalInfo.approvalRoutes))) {
                        error = new DError('TIZENJOB023');
                    }
                } else { // approvalInfo must haven't
                    if (job.options.approvalInfo) {
                        error = new DError('TIZENJOB017', {
                            distName: job.distName
                        });
                    }
                }
                cb(error);
            }
        ],
        function (err) {
            callback(err, job);
        });
    }
}


// NOTE. MUST strip unnecessary information for reducing object size
//       if not, DNODE RPC cannnot receive callback
module.exports.stripJob = stripTizenJob;
function stripTizenJob(job) {
    if (job.snapshot) {
        job.snapshot = null;
    }
    if (job.distribution) {
        job.distribution = null;
    }
}

function sendEmail(jobResult, job, monitor, callback) {
    var subject = '';
    var msg = '';
    var targets = job.userEmail;

    async.waterfall([
        function (scb) {
            if (job.projectType === 'Tizen-Multi') {
                msg += 'MultiJob ID: ' + job.id + '\n';
                msg += 'Distribution: ' + job.distName + '\n';
                msg += 'SubJobs:\n';

                job.subJobs.forEach(function (sjob) {
                    msg += ' ID.' + sjob.id + ' ' + sjob.status + ') ' + sjob.projectName + '[' + sjob.environmentName + ']\n';
                    if (sjob.error_code) {
                        msg += ' - Error Code:' + sjob.error_code + '\n';
                        msg += ' - Error Message:' + sjob.statusInfo + '\n';
                    }
                    msg += ' - Working Time' + sjob.startTime + ' ~ ' + sjob.endTime + '\n';
                    msg += '\n';
                });
            } else {
                msg += 'JOB ID: ' + job.id + '\n';
                msg += 'Distribution: ' + job.distName + '\n';
                msg += 'Project: ' + job.projectName + '\n';
                msg += 'TargetOS: ' + job.environmentName + '\n';
                msg += 'StartTime: ' + job.startTime + ' ~\n';
            }
            scb(null);
        }, function (scb) {
            if (jobResult) {
                subject = '[JOB-' + job.id + '] Build Failed';
                if (job.projectType !== 'Tizen-Multi') {
                    msg += 'Error: ' + jobResult.message + '\n';
                }
            } else {
                subject = '[JOB-' + job.id + '] Build succeeded';
            }
            scb(null);
        }, function (scb) {
            if (job.approvalId) {
                sendToApprovalRoute(job, subject, msg, scb);
            } else {
                dibs.rpc.messenger.notify('email', subject, targets, msg, scb);
            }
        }], callback);
}

module.exports.sendEmail = sendEmail;

function sendToApprovalRoute(job, subject, message, callback) {
    dibs.rpc.approvalmgr.getApproval(job.approvalId, function (err, approval) {
        if (!err && approval.submissionStatus === 'APPROVED') {
            async.eachLimit(approval.approvalRoutes, 1, function (target, cb) {
                dibs.rpc.messenger.notify('email', subject, target.email, message, function (err) {
                    if (err) {
                        dibs.log.warn('Fail sending email to ' + target.email);
                    }
                    cb(null);
                });
            }, function () {
                callback(null);
            });
        } else {
            dibs.rpc.messenger.notify('email', subject, job.userEmail, message, callback);
        }
    });
}
