<%
(function () {

    var log = new Log();
    var carbon = require('carbon');    
    var timeRangeUtil = Packages.org.wso2.analytics.shared.util.time.TimeRangeUtils;
    var common = require('isanalytics-common.jag');
    
    var CONTENT_TYPE_JSON = "application/json";
    var TYPE = "type";
    var HTTP_INTERNAL_ERROR = 500;
    var HTTP_USER_NOT_AUTHENTICATED = 403;

    //operation types
    var TYPE_TOP_LONGEST_SESSIONS = 21;
    var TYPE_AVERAGE_SESSION_DURATION = 22;
    var TYPE_SESSION_COUNT_OVER_TIME = 23;
    var TYPE_SESSION_USERNAME_LIST = 24;
    var TYPE_SESSION_CHANGE_OVER_TIME = 26;
    var TYPE_SESSION_DATA_TABLE = 27;

    response.contentType = CONTENT_TYPE_JSON;

    loggedInUser = common.getLoggedInUser();

    if (loggedInUser == null) {
        log.error("user is not authenticated!");
        response.status = HTTP_USER_NOT_AUTHENTICATED;
        print('{ "status": "Failed", "message": "User is not authenticated." }');
        return;
    }

    var connector = common.getConnector();

    var type = 0;
    var typeParam = request.getParameter(TYPE);
    if (typeParam != null) {
        type = parseInt(typeParam);
    }

    if (type == 0) {
        log.error("operation type is not specified!");
        response.status = HTTP_INTERNAL_ERROR;
        print('{ "status": "Failed", "message": "Operation type is not specified" }');
        return;
    }

    if (connector != null && loggedInUser != null) {

        var result = null;
        var query = null;
        var resp = null;

        var timeFrom = request.getParameter("timeFrom");
        var timeTo = request.getParameter("timeTo");
        var listnedAdditionalUserPrefs = request.getParameter("listnedAdditionalUserPrefs");
        var idpType = request.getParameter("idpType");
        var timeUnit = timeRangeUtil.getSuitableTimeRangeUnit(timeFrom, timeTo);

        switch (type) {          
            case TYPE_TOP_LONGEST_SESSIONS:
            {
                result = [];
                var data = [];
                var start = parseInt(request.getParameter("start"));
                var length = parseInt(request.getParameter("count"));

                var tableName = "ORG_WSO2_IS_ANALYTICS_STREAM_SESSIONINFO";
                var timeNow = new Date().getTime();

                query = stringify({
                    fieldName: "sessionId", //field which is indexed as a FACET
                    categoryPath: [], //Path being drilled down, optional
                    query: "startTimestamp : [" + 0 + " TO " + timeTo + "] AND (endTimestamp : [" + timeFrom + " TO " + timeNow + "] OR isActive:true)",
                    scoreFunction: "duration", //score function
                    start: start,
                    count: length
                });

                resp = connector.drillDownCategories(loggedInUser, tableName, query);
                var dataPoints = JSON.parse(resp.getMessage());
                var obj = dataPoints.categories;

                var sessionIds = [];
                var queryString = "";
                for (var key in obj) {
                    sessionIds.push(key);
                    if(queryString.length != 0) {
                        queryString += " OR ";
                    }
                    queryString += "sessionId:" + key;
                }

                query = stringify({
                    query: queryString,
                    start: start,
                    count: length,
                    "sortBy": [
                        {
                            "field": "duration",
                            "sortType": "DESC"
                        }
                    ]
                });

                resp = connector.search(loggedInUser, tableName, query);
                var dataPoints = JSON.parse(resp.getMessage());
                var count = connector.searchCount(loggedInUser, tableName, query).getMessage();

                for (i = 0; i < dataPoints.length; i++) {
                    var temp = [];
                    if (dataPoints[i] != null) {
                        var index = start + i + 1;
                        var username = dataPoints[i]["values"]["userName"];
                        var duration = dataPoints[i]["values"]["duration"];
                        data.push({
                            "username": username + " " + index,
                            "duration": duration / 1000
                        });
                    }
                }
                result.push(data);
                result.push(count);
                break;
            }
            case TYPE_AVERAGE_SESSION_DURATION:
            {
                result = [];
                var data = [];
                dataPointsArray = [];
                var start = parseInt(request.getParameter("start"));
                var length = parseInt(request.getParameter("count"));

                if (timeUnit == "SECOND" || timeUnit == "MINUTE") {
                    timeUnit = "HOUR";
                } else if (timeUnit == "MONTH" || timeUnit == "YEAR") {
                    timeUnit = "DAY";
                }

                var tableName = "ORG_WSO2_IS_ANALYTICS_STREAM_SESSIONAGGREGATESTATPER" + timeUnit;

                query = stringify({
                    tableName: tableName,
                    groupByField: "userName",
                    aggregateLevel: 0,
                    query: "bucketStart : [" + timeFrom + " TO " + timeTo + "] AND bucketEnd : [" + timeFrom + " TO " + timeTo + "]",
                    aggregateFields: [
                        {
                            fieldName: "averageSession",
                            aggregate: "AVG",
                            alias: "averageSession"
                        }
                    ]
                });

                resp = connector.searchWithAggregates(loggedInUser, tableName, query);
                var dataPoints = JSON.parse(resp.getMessage());
                var count = dataPoints.length;

                for (i = 0; i < dataPoints.length; i++) {
                    var temp = [];
                    if (dataPoints[i] != null) {
                        var username = dataPoints[i]["values"]["userName"];
                        var duration = dataPoints[i]["values"]["averageSession"];
                        data.push({
                            "username": username,
                            "duration": duration / 1000
                        });
                    }
                }

                // sort average values
                var insert = function (array, rightIndex, value) {
                    for (var j = rightIndex; j > 0 && array[j - 1]["duration"] < value["duration"]; j--) {
                        array[j] = array[j - 1];
                    }
                    array[j] = value;
                };

                for (var i = 0; i < data.length; i++) {
                    insert(data, i, data[i]);
                }

                result.push(data.slice(start, start + length));
                result.push(count);
                break;
            }
            case TYPE_SESSION_COUNT_OVER_TIME:
            {
                result = [];
                dataPointsArray = [];
                var start = parseInt(request.getParameter("start"));
                var length = parseInt(request.getParameter("count"));

                if (timeUnit == "SECOND" || timeUnit == "MINUTE") {
                    timeUnit = "HOUR";
                } else if (timeUnit == "MONTH" || timeUnit == "YEAR") {
                    timeUnit = "DAY";
                }

                var tableName = "ORG_WSO2_IS_ANALYTICS_STREAM_SESSIONINFO";

                var labels = ["< 15 mins", "< 1 hr", "< 12 hrs", "< 24 hrs", "> 24 hrs"];
                var timeNow = new Date().getTime();

                query = stringify({
                    tableName: tableName,
                    rangeField: "duration",
                    "ranges":[
                        {
                            "label":"< 15 mins",
                            "from":0,
                            "to":900000
                        },
                        {
                            "label":"< 1 hr",
                            "from":900001,
                            "to":3600000
                        },
                        {
                            "label":"< 12 hrs",
                            "from":3600000,
                            "to":43200000
                        },
                        {
                            "label":"< 24 hrs",
                            "from":43200001,
                            "to":86400000
                        },
                        {
                            "label":"> 24 hrs",
                            "from":86400000,
                            "to":9223372036854775807
                        }
                    ],
                    query: "startTimestamp : [" + 0 + " TO " + timeTo + "] AND (endTimestamp : [" + timeFrom + " TO " + timeNow + "] OR isActive:true)"
                });

                resp = connector.drillDownRangeCount(loggedInUser, tableName, query);
                var dataPoints = JSON.parse(resp.getMessage());

                for (var i=0; i<dataPoints.length; i++) {
                    dataPointsArray.push({
                        "duration": dataPoints[i].label,
                        "sessionCount": dataPoints[i].count
                    });
                }

                result.push(dataPointsArray);
                result.push(dataPoints.length);
                break;
            }
            case TYPE_SESSION_USERNAME_LIST:
            {
                result = [];
                dataPointsArray = [];

                if (timeUnit == "SECOND" || timeUnit == "MINUTE") {
                    timeUnit = "HOUR";
                } else if (timeUnit == "MONTH" || timeUnit == "YEAR") {
                    timeUnit = "DAY";
                }

                var tableName = "ORG_WSO2_IS_ANALYTICS_STREAM_SESSIONAGGREGATESTATPER" + timeUnit;

                query = stringify({
                    fieldName: "userName", //field which is indexed as a FACET
                    categoryPath: [], //Path being drilled down, optional
                    query: "bucketStart : [" + timeFrom + " TO " + timeTo + "] AND bucketEnd : [" + timeFrom + " TO " + timeTo + "]",
                });

                resp = connector.drillDownCategories(loggedInUser, tableName, query);

                var dataPoints = JSON.parse(resp.getMessage());

                var obj = dataPoints.categories;

                for (var key in obj) {
                    if (obj.hasOwnProperty(key)) {
                        result.push({
                            "userName": key
                        });
                    }
                }
                break;
            }
            case TYPE_SESSION_CHANGE_OVER_TIME:
            {
                result = [];
                var data = [];
                dataPointsArray = [];
                var start = parseInt(request.getParameter("start"));
                var length = parseInt(request.getParameter("count"));

                if (timeUnit == "SECOND") {
                    timeUnit = "MINUTE";
                } else if (timeUnit == "DAY" || timeUnit == "MONTH" || timeUnit == "YEAR") {
                    timeUnit = "HOUR";
                }

                // querying for session change
                var tableName = "ORG_WSO2_IS_ANALYTICS_STREAM_SESSIONSTATPER" + timeUnit;


                query = stringify({
                    query: "bucketStart : [" + timeFrom + " TO " + timeTo + "] AND bucketEnd : [" + timeFrom + " TO " + timeTo + "]",
                    start: start,
                    count: length
                });

                var resp = connector.search(loggedInUser, tableName, query);
                var dataPoints = JSON.parse(resp.getMessage());
                var count = connector.searchCount(loggedInUser, tableName, query);

                // querying for active session count
                var tableNameActiveSessions = "IS-SESSION-ACTIVE-COUNT";

                queryActiveSessions = stringify({
                    query: "*:*",
                    start: start,
                    count: length
                });

                var respActiveCount = connector.search(loggedInUser, tableNameActiveSessions, queryActiveSessions);
                var dataPointsActiveCount = JSON.parse(respActiveCount.getMessage());
                var activeCount = dataPointsActiveCount[0]["values"]["activeCount"];

                for (i = 0; i < dataPoints.length; i++) {
                    var temp = [];
                    if (dataPoints[i] != null) {
                        var timestamp = dataPoints[i]["values"]["bucketId"];
                        var activeSessionCount = dataPoints[i]["values"]["activeSessionCount"];
                        var newSessionCount = dataPoints[i]["values"]["newSessionCount"];
                        var terminatedSessionCount = dataPoints[i]["values"]["terminatedSessionCount"];

                        data.push({
                            "timestamp": Number(timestamp),
                            "sessionCount": activeSessionCount,
                            "sessionType": "Active"
                        });
                        data.push({
                            "timestamp": Number(timestamp),
                            "sessionCount": newSessionCount,
                            "sessionType": "New"
                        });
                        data.push({
                            "timestamp": Number(timestamp),
                            "sessionCount": terminatedSessionCount,
                            "sessionType": "Terminated"
                        });
                    }
                }

                result.push(data);
                result.push({
                    "activeCount": activeCount
                });

                break;
            }
            case TYPE_SESSION_DATA_TABLE:
            {

                var columns = ["sessionId", "userName", "startTimestamp", "terminationTimestamp", "endTimestamp", "duration",
                    "isActive", "userstoreDomain", "IP", "tenantDomain", "rememberMeFlag", "_timestamp"];
                var result = {};
                var data = [];
                var start = parseInt(request.getParameter("start"));
                var length = parseInt(request.getParameter("length"));
                var draw = request.getParameter("draw");

                var sortByColumnNo = parseInt(request.getParameter("order[0][column]"));
                var sortType = request.getParameter("order[0][dir]").toUpperCase();
                var tableName = "ORG_WSO2_IS_ANALYTICS_STREAM_SESSIONINFO";

                var query = stringify({
                    "query": "_timestamp : [" + timeFrom + " TO " + timeTo + "]",
                    "start": start,
                    "count": length
                });

                var resp = connector.search(loggedInUser, tableName, query);
                var dataPoints = JSON.parse(resp.getMessage());

                var count = connector.searchCount(loggedInUser, tableName, query);
                var limit = count.getMessage();

                for (i = 0; i < dataPoints.length; i++) {
                    var temp = [];

                    for (j = 0; j < columns.length; j++) {
                        var column = columns[j];
                        if (dataPoints[i] != null) {
                            if (column == "_timestamp") {
                                var value = dataPoints[i]["timestamp"];
                                var date = new Date(value);
                                temp.push(date.toLocaleString());
                            } else {
                                var value = dataPoints[i]["values"][column];
                                temp.push(value);
                            }
                        }
                    }
                    data.push(temp);
                }

                result["draw"] = draw;
                result["data"] = data;

                if (dataPoints.length < length) {
                    limit = start + length;
                }
                result["recordsFiltered"] = limit;
                result["recordsTotal"] = limit;
                break;
            }
            default:
            {
                result = '{ "status": "Failed", "message": "Unidentified operation" }';
            }
        }

        if (result != null) {
            if (log.isDebugEnabled()) {
                log.debug("value of result: " + result);
            }
            var finalResult;
            if (type == TYPE_SESSION_DATA_TABLE) {
                finalResult = result;
            } else {
                finalResult = {
                    status: "success",
                    message: result
                }
            }
            print(finalResult);
        }
    }
    else {
        print('{ "status": "Failed", "statusCode": "500", "message": "AnalyticsCachedWebServiceConnector is unavailable" }');
    }
}());

%>