/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

const CronJob = require('cron').CronJob;
const moment = require('moment');
const common = require('./lib/common');
const Database = require('./lib/Database');
const config = require('./lib/config');

function main(params) {

    if (!params.triggerName) {
        return common.sendError(400, 'no trigger name parameter was provided');
    }

    var triggerParts = common.parseQName(params.triggerName);
    var triggerData = {
        apikey: params.authKey,
        name: triggerParts.name,
        namespace: triggerParts.namespace,
        additionalData: common.constructObject(params.additionalData),
    };
    var triggerID = config.constructTriggerID(triggerData);

    var workers = params.workers instanceof Array ? params.workers : [];
    var deleteAfterFireArray = ['false', 'true', 'rules'];
    var db;

    if (params.__ow_method === "post") {

        if (typeof params.trigger_payload === 'string') {
            params.trigger_payload = {payload: params.trigger_payload};
        }

        var newTrigger = {
            payload: params.trigger_payload || {},
            maxTriggers: params.maxTriggers || -1,
            status: {
                'active': true,
                'dateChanged': Date.now()
            }
        };

        if (params.fireOnce) {
            if (!params.date) {
                return common.sendError(400, 'alarms once trigger feed is missing the date parameter');
            }
            var date = validateDate(params.date, 'date');
            if (date !== params.date) {
                return common.sendError(400, date);
            }
            newTrigger.date = date;

            if (params.deleteAfterFire) {
                var deleteAfterFire = ('' + params.deleteAfterFire).trim().toLowerCase();
                if (deleteAfterFireArray.indexOf(deleteAfterFire) === -1) {
                    return common.sendError(400, 'deleteAfterFire parameter must be one of [false, true, rules].');
                }
                newTrigger.deleteAfterFire = deleteAfterFire;
            }
        }
        else {
            var cronHandle;

            if (params.isInterval) {
                if (!params.minutes) {
                    return common.sendError(400, 'interval trigger feed is missing the minutes parameter');
                }
                if (+params.minutes !== parseInt(params.minutes)) {
                    return common.sendError(400, 'the minutes parameter must be an integer');
                }
                var minutesParam = parseInt(params.minutes);

                if (minutesParam <= 0) {
                    return common.sendError(400, 'the minutes parameter must be an integer greater than zero');
                }
                newTrigger.minutes = minutesParam;
            }
            else {
                if (!params.cron) {
                    return common.sendError(400, 'alarms trigger feed is missing the cron parameter');
                }

                try {
                    cronHandle = new CronJob(params.cron, function() {}, undefined, false, params.timezone);
                    //validate cron granularity if 5 fields are allowed instead of 6
                    if (params.limitCronFields && hasSecondsGranularity(params.cron)) {
                        return common.sendError(400, 'cron pattern is limited to 5 fields with 1 minute as the finest granularity');
                    }
                    newTrigger.cron = params.cron;
                    newTrigger.timezone = params.timezone;
                    newTrigger.strict = params.strict;
                } catch(ex) {
                    var message = ex.message !== 'Invalid timezone.' ? `cron pattern '${params.cron}' is not valid` : ex.message;
                    return common.sendError(400, message);
                }
            }

            if (params.startDate) {
                var startDate = validateDate(params.startDate, 'startDate');
                if (startDate !== params.startDate) {
                    return common.sendError(400, startDate);
                }
                newTrigger.startDate = startDate;
            }
            else if (params.isInterval) {
                //if startDate was not given we will start it 30 seconds
                //from now since startDate must be in the future
                newTrigger.startDate = Date.now() + (1000 * 30);
            }

            if (params.maxTriggers && params.stopDate) {
                if (params.isInterval) {
                    return common.sendError(400, 'maxTriggers is not supported for the interval trigger feed');
                }
                else {
                    return common.sendError(400, 'maxTriggers is not allowed when the stopDate parameter is specified');
                }
            }
            else if (params.stopDate) {
                var stopDate = validateDate(params.stopDate, 'stopDate', newTrigger.startDate);
                if (stopDate !== params.stopDate) {
                    return common.sendError(400, stopDate);
                }
                newTrigger.stopDate = stopDate;

                //verify that the first scheduled trigger fire will occur before the stop date
                if (cronHandle && cronHandle.nextDate().isAfter(new Date(params.stopDate))) {
                    return common.sendError(400, 'the first scheduled trigger fire is not until after the stop date');
                }
            }
        }

        return new Promise(function (resolve, reject) {
            common.verifyTriggerAuth(triggerData, false)
            .then(() => {
                db = new Database(params.DB_URL, params.DB_NAME, params.DB_USERNAME, params.DB_PASSWORD);
                return db.getWorkerID(workers);
            })
            .then((worker) => {
                console.log('trigger will be assigned to worker ' + worker);
                newTrigger.worker = worker;
                Object.assign(newTrigger, triggerData);
                return db.createTrigger(triggerID, newTrigger);
            })
            .then(() => {
                resolve({
                    statusCode: 200,
                    headers: {'Content-Type': 'application/json'},
                    body: {'status': 'success'}
                });
            })
            .catch(err => {
                reject(err);
            });
        });

    }
    else if (params.__ow_method === "get") {
        return new Promise(function (resolve, reject) {
            common.verifyTriggerAuth(triggerData, false)
            .then(() => {
                db = new Database(params.DB_URL, params.DB_NAME, params.DB_USERNAME, params.DB_PASSWORD);
                return db.getTrigger(triggerID);
            })
            .then(doc => {
                var body = {
                    config: {
                        name: doc.name,
                        namespace: doc.namespace,
                        payload: doc.payload
                    },
                    status: {
                        active: doc.status.active,
                        dateChanged: moment(doc.status.dateChanged).utc().valueOf(),
                        dateChangedISO: moment(doc.status.dateChanged).utc().format(),
                        reason: doc.status.reason
                    }
                };
                var strict = process.env.ALARM_DELAY_DEFAULT_STRICT === "true";
                if (doc.strict !== undefined) {
                    strict = doc.strict;
                }
                body.config.strict = strict;
                if (doc.date) {
                    body.config.date = doc.date;
                    body.config.deleteAfterFire = doc.deleteAfterFire;
                }
                else {
                    body.config.startDate = doc.startDate;
                    body.config.stopDate = doc.stopDate;
                    if (doc.minutes) {
                        body.config.minutes = doc.minutes;
                    }
                    else {
                        body.config.cron = doc.cron;
                        body.config.timezone = doc.timezone;
                    }
                }
                resolve({
                    statusCode: 200,
                    headers: {'Content-Type': 'application/json'},
                    body: body
                });
            })
            .catch(err => {
                reject(err);
            });
        });
    }
    else if (params.__ow_method === "put") {

        return new Promise(function (resolve, reject) {
            var updatedParams = {};

            common.verifyTriggerAuth(triggerData, false)
            .then(() => {
                db = new Database(params.DB_URL, params.DB_NAME, params.DB_USERNAME, params.DB_PASSWORD);
                return db.getTrigger(triggerID);
            })
            .then(trigger => {
                if (trigger.status && trigger.status.reason && trigger.status.reason.kind === 'ADMIN') {
                    return reject(common.sendError(400, `${params.triggerName} cannot be updated because it was disabled by an admin.  Please contact support for further assistance`));
                }

                if (params.trigger_payload) {
                    updatedParams.payload = common.constructObject(params.trigger_payload, true);
                }

                if (trigger.date) {
                    if (params.date) {
                        var date = validateDate(params.date, 'date');
                        if (date !== params.date) {
                            return reject(common.sendError(400, date));
                        }
                        updatedParams.date = date;
                    }

                    if (params.deleteAfterFire) {
                        var deleteAfterFire = ('' + params.deleteAfterFire).trim().toLowerCase();
                        if (deleteAfterFireArray.indexOf(deleteAfterFire) === -1) {
                            return reject(common.sendError(400, 'deleteAfterFire parameter must be one of [false, true, rules].'));
                        }
                        updatedParams.deleteAfterFire = deleteAfterFire;
                    }
                }
                else {
                    if (trigger.minutes) {
                        if (params.minutes) {
                            if (+params.minutes !== parseInt(params.minutes)) {
                                return reject(common.sendError(400, 'the minutes parameter must be an integer'));
                            }
                            var minutesParam = parseInt(params.minutes);

                            if (minutesParam <= 0) {
                                return reject(common.sendError(400, 'the minutes parameter must be an integer greater than zero'));
                            }
                            updatedParams.minutes = minutesParam;
                        }
                    }
                    else {
                        if (params.cron || params.timezone) {
                            var cron = params.cron || trigger.cron;
                            var timezone = params.timezone || trigger.timezone;
                            try {
                                cronHandle = new CronJob(cron, function() {}, undefined, false, timezone);
                                //validate cron granularity if 5 fields are allowed instead of 6
                                if (params.cron && params.limitCronFields && hasSecondsGranularity(params.cron)) {
                                    return reject(common.sendError(400, 'cron pattern is limited to 5 fields with 1 minute as the finest granularity'));
                                }
                            } catch (ex) {
                                var message = ex.message !== 'Invalid timezone.' ? `cron pattern '${cron}' is not valid` : ex.message;
                                return reject(common.sendError(400, message));
                            }
                            if (params.cron) {
                                updatedParams.cron = params.cron;
                            }
                            if (params.timezone) {
                                updatedParams.timezone = params.timezone;
                            }
                        }
                        if(params.hasOwnProperty("strict")) {
                            updatedParams.strict = params.strict;
                        }
                    }

                    if (params.startDate) {
                        var startDate = validateDate(params.startDate, 'startDate');
                        if (startDate !== params.startDate) {
                            return reject(common.sendError(400, startDate));
                        }
                        updatedParams.startDate = startDate;
                    }

                    if (params.stopDate) {
                        var stopDate = validateDate(params.stopDate, 'stopDate', params.startDate || trigger.startDate);
                        if (stopDate !== params.stopDate) {
                            return reject(common.sendError(400, stopDate));
                        }
                        updatedParams.stopDate = stopDate;
                    }
                    else if (params.startDate && trigger.stopDate) {
                        //need to verify that new start date is before existing stop date
                        if (new Date(params.startDate).getTime() >= new Date(trigger.stopDate).getTime()) {
                            return reject(common.sendError(400, `startDate parameter '${params.startDate}' must be less than the stopDate parameter '${trigger.stopDate}'`));
                        }

                    }
                }

                if (Object.keys(updatedParams).length === 0) {
                    return reject(common.sendError(400, 'no updatable parameters were specified'));
                }
                return db.disableTrigger(trigger._id, trigger, 0, 'updating');
            })
            .then(triggerID => {
                return db.getTrigger(triggerID);
            })
            .then(trigger => {
                return db.updateTrigger(trigger._id, trigger, updatedParams, 0);
            })
            .then(() => {
                resolve({
                    statusCode: 200,
                    headers: {'Content-Type': 'application/json'},
                    body: {'status': 'success'}
                });
            })
            .catch(err => {
                reject(err);
            });
        });
    }
    else if (params.__ow_method === "delete") {

        return new Promise(function (resolve, reject) {
            common.verifyTriggerAuth(triggerData, true)
            .then(() => {
                db = new Database(params.DB_URL, params.DB_NAME, params.DB_USERNAME, params.DB_PASSWORD);
                return db.getTrigger(triggerID);
            })
            .then(trigger => {
                return db.disableTrigger(trigger._id, trigger, 0, 'deleting');
            })
            .then(triggerID => {
                return db.deleteTrigger(triggerID, 0);
            })
            .then(() => {
                resolve({
                    statusCode: 200,
                    headers: {'Content-Type': 'application/json'},
                    body: {'status': 'success'}
                });
            })
            .catch(err => {
                reject(err);
            });
        });
    }
    else {
        return common.sendError(400, 'unsupported lifecycleEvent');
    }
}

function validateDate(date, paramName, startDate) {

    var dateObject = new Date(date);

    if (isNaN(dateObject.getTime())) {
        return `${paramName} parameter '${date}' is not a valid Date`;
    }
    else if (Date.now() >= dateObject.getTime()) {
        return `${paramName} parameter '${date}' must be in the future`;
    }
    else if (startDate && dateObject <= new Date(startDate).getTime()) {
        return `${paramName} parameter '${date}' must be greater than the startDate parameter '${startDate}'`;
    }
    else {
        return date;
    }

}

function hasSecondsGranularity(cron) {

    var fields = (cron + '').trim().split(/\s+/);
    return fields.length > 5 && fields[fields.length - 6] !== '0';
}

exports.main = main;
