/**
 * job-trigger-period.js
 * Copyright (c) 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 async = require('async');
var _ = require('underscore');

var dibs = require('../../core/dibs.js');
var DError = require('../../core/exception.js');


module.exports.addTrigger = addTrigger;
module.exports.searchTrigger = searchTrigger;
module.exports.modifyTrigger = modifyTrigger;
module.exports.removeTrigger = removeTrigger;


function checkDistribution(distName, callback) {
    dibs.rpc.datamgr.searchDistributions({name: distName}, function (err, dists) {
        if (err) {
            callback(err);
        } else {
            if (_.size(dists) === 0) {
                dibs.log.warn('[period trigger] distributions are empty');
                callback(null, true);
            } else if (dists[0] && dists[0].status !== 'OPEN') {
                dibs.log.info('[period trigger] ' + dists[0].name + ' distribution status: ' + dists[0].status);
                callback(null, true);
            } else {
                callback(null, false);
            }
        }
    });
}


function checkProject(projectId, callback) {
    dibs.rpc.datamgr.searchProjects({id: projectId}, function (err, prjs) {
        if (err) {
            callback(err, null);
        } else {
            if (_.size(prjs) === 0) {
                dibs.log.warn('[period trigger] projects are empty');
                callback(null, null);
            } else if (prjs[0] && prjs[0].status !== 'OPEN') {
                dibs.log.info('[period trigger] ' + prjs[0].distName + ':' + prjs[0].name +
                    ' project status: ' + prjs[0].status);
                callback(null, null);
            } else {
                dibs.log.info('[period trigger] search projects successfully! ' +
                    prjs[0].distName + ':' + prjs[0].name);
                callback(null, prjs[0]);
            }
        }
    });
}


function checkAndAddJob(project, callback) {
    var jobCondition = {
        project_name: project.name,
        distName: project.distName,
        arrange: 'DESC',
        count: 1
    };

    dibs.rpc.datamgr.searchJobs(jobCondition, function (err, jobs) {
        if (err) {
            callback(err);
        } else {
            var isJobWorking = false;
            _.each(jobs, function (job) {
                if (_.contains(['JUST_CREATED', 'INITIALIZING', 'INITIALIZED', 'WORKING'], job.status)) {
                    isJobWorking = true;
                }
            });

            if (isJobWorking) {
                dibs.log.info('[period trigger] ignore adding jobs because project is working ... ' +
                    project.distName + ':' + project.name);
                callback(null);
            } else {
                dibs.log.info('[period trigger] adding trigger jobs ... ' +
                    project.distName + ':' + project.name);
                dibs.rpc.jobmgr.addJob('sync-manager@user', project.distName, project.name, '',
                    { environment: project.environments }, callback);
            }
        }
    });
}


// add scheduled action
function addTrigger(trigger, callback) {
    if (!trigger) {
        return callback(new DError('JOBTRGR001', { argument: 'trigger', value: trigger }));
    }

    var triggerData = trigger.data;
    var projectId = triggerData.projectId;

    async.waterfall([
        function (cb) {
            dibs.rpc.datamgr.searchProjects({id: projectId}, function (err, projects) {
                if (err) {
                    cb(err);
                } else {
                    if (projects.length === 0) {
                        cb(new DError('JOBTRGR002', { id: projectId }));
                    } else {
                        cb(err, _.clone(projects[0]));
                    }
                }
            });
        },
        function (project, cb) {
            var triggerPeriodSec = 0;
            if (triggerData.period) {
                triggerPeriodSec = (Number(triggerData.period) * 1000 * 60);
            }

            dibs.log.info('[period trigger] register trigger action ... ' +
                    project.distName + ':' + project.name + ' period: ' + triggerPeriodSec);

            dibs.thisServer.addScheduledAction(trigger.name, {period: triggerPeriodSec}, function (cb1) {
                dibs.log.info('[period trigger] execute trigger routine... ' +
                    project.distName + ':' + project.name);

                async.waterfall([
                    function (cb2) {
                        // check distribution status
                        dibs.log.info('[period trigger] check distribution status ');
                        checkDistribution(project.distName, cb2);
                    },
                    function (skippingTrigger, cb2) {
                        if (skippingTrigger) {
                            dibs.log.info('[period trigger] skipping trigger for ' +
                                project.distName + ':' + project.name);
                            cb2(null, null);
                        } else {
                            // check project status
                            checkProject(project.id, cb2);
                        }
                    },
                    function (triggerProject, cb2) {
                        if (!triggerProject) {
                            dibs.log.warn('[period trigger] failed to get trigger project... ' +
                                project.distName + ':' + project.name);
                            cb2(null);
                        } else {
                            checkAndAddJob(triggerProject, cb2);
                        }
                    }
                ],
                function (err) {
                    if (err) {
                        dibs.log.error(err);
                    }
                    cb1(err);
                });
            });

            cb(null);
        }
    ],
    function (err) {
        if (err) {
            dibs.log.error(err);
        }

        callback(err);
    });
}

// remove scheduled action
function removeTrigger(trigger, callback) {
    if (!trigger) {
        return callback(new DError('JOBTRGR001', { argument: 'trigger', value: trigger }));
    }

    dibs.thisServer.removeScheduledAction(trigger.name);
    callback(null);
}


// get scheduled action
function searchTrigger(trigger, callback) {
    if (!trigger) {
        return callback(new DError('JOBTRGR001', { argument: 'trigger', value: trigger }));
    }

    callback(null, dibs.thisServer.getScheduledAction(trigger.name));
}


function modifyTrigger(trigger, callback) {
    if (!trigger) {
        return callback(new DError('JOBTRGR001', { argument: 'trigger', value: trigger }));
    }

    callback(null);
}
