/*************************************************************************
*
* ADOBE CONFIDENTIAL
* ___________________
*
*  Copyright 2013 Adobe Systems Incorporated
*  All Rights Reserved.
*
* NOTICE:  All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any.  The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated and its
* suppliers and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
**************************************************************************/

/*jslint node: true */
"use strict";

var sharedCloudConfig = require('../handlers/sharedCloudConfig'),
    utils = require('../utils/userFeaturesUtils'),
    https = require(sharedCloudConfig.getSharedCloudProtocol()),
    step = require('step'),
    logger = require('winston'),
    awsUtils = require('../aws/awsUtils'),
    IMS_CLIENT_ID = 'webpagraphics',
    lastHealthcheckTimestamp = null,
    imsStatusOk = false,
    sharedCloudStatusOk = false,
    awsStatusOk = false,
    REMOTECALL_TIMEOUT = 45000; //Set the timeout to 45 seconds so we timeout before nginx does

function asynchCheckIMS(callback) {
    var options = {
            host: sharedCloudConfig.getIMSHost(),
            path: '/ims/login/v1/token?client_id=' + IMS_CLIENT_ID + '&username=badUsername@badusername.org&password=badPassword&scope=openid',
            method: 'GET'
        },
        myreq = https.request(options, function (response) {
            response.on('data', function () {
            });
            response.on('end', function () {
                callback(null, true);
            });
        });
    var startTime = new Date().getTime();
    myreq.on('socket', function (socket) {
        socket.setTimeout(REMOTECALL_TIMEOUT);
        logger.info("asynchCheckIMS - Checking IMS health. Setting timeout to " + REMOTECALL_TIMEOUT + " millis");

        socket.on('timeout', function() {
            logger.warn("asynchCheckIMS - timed out waiting for IMS. Waited " + REMOTECALL_TIMEOUT + " millis");
            myreq.abort();
        });
    });
    myreq.on('finish', function () {
        logger.info("asynchCheckIMS - checked IMS health. Completed in: " + (new Date().getTime() - startTime) + " millis");
    });
    myreq.on('error', function (err) {
        logger.warn("asynchCheckIMS - IMS error: " + err);
        callback(err, false);
    });
    myreq.end();
}

function asynchCheckAWS(callback) {
    var startTime = new Date().getTime();
    logger.info("asynchCheckAWS - Checking AWS health.");
    awsUtils.countEnabledUsers(function (err, data) {
        if (err) {
            logger.warn("asynchCheckAWS - AWS error: " + err);
            logger.warn("asynchCheckAWS - AWS elapsed time until error: " + (new Date().getTime() - startTime) + " millis");
            callback(err, false);
        } else {
            logger.info("asynchCheckAWS - Checked AWS health. Completed in " + (new Date().getTime() - startTime) + " millis");
            callback(null, true);
        }
    });
}

function asynchCheckSharedCloud(callback) {
    var startTime = new Date().getTime();
    //Do a simple version check call in shared cloud to see if it is up
    var options = {
            host: sharedCloudConfig.getSharedCloudHost(),
            port: sharedCloudConfig.getSharedCloudPort(),
            path: '/api/v1/',
            method: 'GET'
        },
        myreq = https.request(options, function (response) {
            response.on('data', function () {
            });
            response.on('end', function () {
                callback(null, true);
            });
        });
    myreq.on('socket', function (socket) {
        socket.setTimeout(REMOTECALL_TIMEOUT);
        logger.info("asynchCheckSharedCloud - Checking Shared Cloud health. Setting timeout to " + REMOTECALL_TIMEOUT + " millis");

        socket.on('timeout', function() {
            logger.warn("asynchCheckSharedCloud - timed out waiting for Shared Cloud. Waited " + REMOTECALL_TIMEOUT + " millis");
            myreq.abort();
        });
    });
    myreq.on('finish', function () {
        logger.info("asynchCheckSharedCloud - checked shared cloud health. Completed in: " + (new Date().getTime() - startTime) + " millis");
    });
    myreq.on('error', function (err) {
        logger.warn("asynchCheckSharedCloud - shared cloud status error: " + err);
        callback(err, false);
    });
    myreq.end();
}

//--- begin REST call handlers
function getSystemHealth(request, response, next) {
    var returnVal = {},
        now = new Date().getTime();
    //Don't call out for status checks more often than once per minute (60000 millis)
    if (!lastHealthcheckTimestamp || (now - lastHealthcheckTimestamp > 60000)) {
        lastHealthcheckTimestamp = new Date().getTime();
        sharedCloudStatusOk  = false;
        awsStatusOk  = false;
        imsStatusOk  = false;

        step(
            function doHealthChecks() {
                asynchCheckIMS(this.parallel());
                asynchCheckAWS(this.parallel());
                asynchCheckSharedCloud(this.parallel());
            },
            function tallyHealthcheckResults(err, imsStatus, awsStatus, scStatus) {
                if (!err) {
                    imsStatusOk  = imsStatus;
                    awsStatusOk  = awsStatus;
                    sharedCloudStatusOk  = scStatus;
                }
                returnVal.status = (imsStatusOk && awsStatusOk && sharedCloudStatusOk) ? "OK" : "SERVICE DOWN";

                response.cache("no-Cache");
                response.writeHead(200, {'Content-Type': 'application/json'});
                response.end(JSON.stringify(returnVal));
            }

        );
    } else {
        //Less than 60 seconds since last status check, use previous results
        returnVal.status = (imsStatusOk && awsStatusOk && sharedCloudStatusOk) ? "OK" : "SERVICE DOWN";
        response.cache("no-Cache");
        response.writeHead(200, {'Content-Type': 'application/json'});
        response.end(JSON.stringify(returnVal));
    }
}

function getThrottleStatus(request, response, next) {
    utils.getThrottleState(function (err, userWillBeEnabled) {
        response.cache("no-Cache");
        response.writeHead(200, {'Content-Type': 'application/json'});
        response.end(JSON.stringify({throttled: !userWillBeEnabled}));
    });
}

function installUtilityHandlers(server) {
    server.get('/api/utility/healthcheck', getSystemHealth);
    server.get('/api/v1/utility/throttlecheck', getThrottleStatus);
}


function installHandlers(server) {
    installUtilityHandlers(server);
}

module.exports = {
    installHandlers : installHandlers
};
