# Source: RallyMethods.js

    /**
     * Created by 212571071 on 7/21/16.
     */
    /**
     * Copyright (c) 2013 - 2014 GE Global Research. All rights reserved.
     * The copyright to the computer software herein is the property of
     * GE Global Research. The software may be used and/or copied only
     * with the written permission of GE Global Research or in accordance
     * with the terms and conditions stipulated in the agreement/contract
     * under which the software has been supplied.
     */

    (function () {
        var logger = require('./Logger.js');
        var request = require('request-promise');
        var RallyHelper = require('./RallyHelper.js');
        var RallyLogger = require('./RallyLogger.js');
        require('dotenv').config();
        var build_num,postOnlyTS;
        if (process.env.build_no != undefined)
            build_num = process.env.build_no;
        else build_num = 1;
        var name, status, duration, keyword, description, glb_test_case_id, glb_test_result_id , test_case_name,
            test_case_description, line, glb_j_length, glb_k_length, User_Story, json, i, error_message ='';
        var stepsArray = [];
        var RallyMethods = function () {
            var stat; var duration1;
            function queryUSTS(USTS, ws, proj,type, callbck) {
                return new Promise(function (resolve, reject) {
                    RallyLogger.getUSTSRef(USTS, ws, proj, type, resolve)
                });
            }
            function queryRH(type, obj, callbck) {
                return new Promise(function (resolve, reject) {
                    RallyLogger.UserPermissions(type, obj, resolve)
                });
            }
            function queryTC(type, test_case_name, project, ws, callbck) {
                return new Promise(function (resolve, reject) {
                    RallyLogger.getObjectRef(type, test_case_name, project, ws, resolve)
                });
            }
            function createTC(opts, ws, proj, callbck_create) {
                return new Promise(function (resolve, reject) {
                    RallyLogger.createTestcase(opts, ws, proj, resolve)
                });
            }
            function createTCR(opts, ws, proj, callbck) {
                return new Promise(function (resolve, reject) {
                    RallyLogger.createTestcaseResult(opts, ws, proj, resolve)
                });
            }
            function createTP(test_plan, ws, proj, callbck) {
                return new Promise(function (resolve, reject) {
                    RallyLogger.createTestPlan(test_plan, ws, proj, resolve)
                });
            }
            function updateTS(tcObj, resp, callbck) {
                return new Promise(function (resolve, reject) {
                    RallyLogger.updateTestSet(tcObj, resp, resolve)
                });
            }
            function updateTC(obj, ws, proj, callbck) {
                return new Promise(function (resolve, reject) {
                    RallyLogger.updateTestCase(obj, ws, proj, resolve)
                });
            }
            function updateTCR(opts, ws, proj, callbck) {
                return new Promise(function (resolve, reject) {
                    RallyLogger.updateTestCaseResult(opts, ws, proj, resolve)
                });
            }
            function TCR(tcObj, resp, callback) {
                return new Promise(function (resolve, reject) {
                    require('./RallyMethods.js').TestCaseResult(tcObj, resp, resolve)
                });
            }

            var k_loop = function(resp,callbck) {
                duration1 = 0; stepsArray = []; var failure = false; var statUndefined = false;
                for (k = 0; k < resp.resp.json[resp.i].elements[resp.j].steps.length; k++) {
                    glb_k_length = resp.resp.json[resp.i].elements[resp.j].steps.length;
                    if ((resp.resp.json[resp.i].elements[resp.j].steps[k].result.duration != undefined) && (resp.resp.json[resp.i].elements[resp.j].steps[k].result.duration != 'undefined')) {
                        duration1 = duration1 + resp.resp.json[resp.i].elements[resp.j].steps[k].result.duration;
                    } else {
                        duration1 = duration1 + 0;
                    }
                    keyword = resp.resp.json[resp.i].elements[resp.j].steps[k].keyword;
                    if(resp.resp.json[resp.i].elements[resp.j].description != undefined) {
                        description = resp.resp.json[resp.i].elements[resp.j].description;
                    } else {
                        description = "";
                    }
                    if(resp.resp.json[resp.i].elements[resp.j].steps[k].result.error_message != undefined) {
                        error_message = resp.resp.json[resp.i].elements[resp.j].steps[k].result.error_message;
                        error_message = error_message.substring(0,400);
                    } else {
                        error_message = "";
                    }
                    if ((resp.resp.json[resp.i].elements[resp.j].steps[k].match != undefined))
                        line = resp.resp.json[resp.i].elements[resp.j].steps[k].match.location;
                    else
                        line = 0;
                    if ((resp.resp.json[resp.i].elements[resp.j].steps[k].keyword != "Before") || (resp.resp.json[resp.i].elements[resp.j].steps[k].keyword != "After")) {
                        name = resp.resp.json[resp.i].elements[resp.j].steps[k].name;
                        if (name != undefined) {
                            stepsArray.push('<br>' + parseInt(k+1) + '. ' + name);
                            //name = name.split(' ').join('_');
                        } else {
                            break;
                        }
                    }
                    if(resp.resp.json[resp.i].elements[resp.j].steps[k].result.status == undefined ||
                        resp.resp.json[resp.i].elements[resp.j].steps[k].result.status == 'undefined'){
                        statUndefined=true;
                    } else {
                        stat = resp.resp.json[resp.i].elements[resp.j].steps[k].result.status;
                    }
                    if (stat == 'failed') {
                        failure=true;
                        //break;
                    }
                }
                if((k == resp.resp.json[resp.i].elements[resp.j].steps.length-1) ) {
                    if(k == 0) {
                        duration1 = ((duration1) / 1000000000.0).toFixed(2);
                        if(failure) stat='failed';
                        else if (statUndefined) stat=undefined;
                    } else {
                        duration1 = ((duration1 / k) / 1000000000.0).toFixed(2);
                        if(failure) stat='failed';
                        else if (statUndefined) stat=undefined;
                    }
                    return callbck(resp);
                }
            }
            function kloop(resp, callbck) {
                return new Promise(function (resolve, reject) {
                    k_loop(resp, resolve)
                });
            }
            var test_case_array = [];
            return {
                /**
                 * Query Revision History, User Story, TestSet, calls methods TestCaseResult
                 * @param tcObj             object w/  User_Story, resp, j, test_case_name, test_case_description, glb_folder_id,
                 * build_num, testset, glb_test_case_id, glb_test_result_id, last_run, glb_i_length, glb_j_length
                 * @param callback          callback on error or when reach end of j loop ( test cases )
                 */
                TestCaseFound: function(tcObj, callback) {
                    var owner_url = tcObj.resp.revision_history_ref;
                    var duration, status;
                    queryRH('', '')
                        .then(function (resp) {
                            var owner = resp.owner_id;
                            kloop(tcObj)
                                .then(function (response) {
                                    tcObj.stepsArray = stepsArray
                                    if(process.env.overwrite_US != undefined && process.env.overwrite_US == "true"){
                                        tcObj.User_Story = process.env.user_story;
                                    }
                                    queryUSTS(tcObj.User_Story, tcObj.ws, tcObj.proj, 'hierarchicalrequirement')
                                        .then(function (resp) {
                                            updateTC({resp: resp, owner:owner, tcObj:tcObj, error:error_message}, tcObj.ws, tcObj.proj)
                                                .then(function (resp) {
                                                    queryUSTS(tcObj.testset, tcObj.ws, tcObj.proj, 'testset')
                                                        .then(function (resp) {
                                                            resp.status = stat;resp.duration = duration1;resp.i = i;
                                                            resp.j = tcObj.j; resp.json = json;
                                                            updateTS(tcObj, resp)
                                                                .then(function (resp) {
                                                                    TCR(tcObj, resp)
                                                                        .then( function(resp) {
                                                                            if (resp == 'step i')
                                                                                return callback('step i');
                                                                            else if (resp == 'step j')
                                                                                return callback('step j');
                                                                            else
                                                                                return callback('callback');
                                                                        });
                                                                }).catch(function(error){
                                                                callback('callback');
                                                            });
                                                        }).catch(function(error){
                                                        callback('callback');
                                                    });
                                                }).catch(function(error){
                                                callback('callback');
                                            });
                                        }).catch(function(error){
                                        callback('callback');
                                    });
                                }).catch(function (error) {
                                callback('callback');
                            });
                        });
                },
                /**
                 * Query User Story, create TestCase, query TestSet, update TestSet, create TestCaseResult
                 * @param tcObj             object w/  User_Story, resp, j, test_case_name, test_case_description,
                 * glb_folder_id, build_num, testset, glb_test_case_id, glb_test_result_id, last_run, glb_i_length, glb_j_length
                 * @param kObj              object w/ duration, status, and response from create test plan
                 * @param callback          callback on error or when reach end of j loop ( test cases )
                 */
                noTestCaseFound: function(tcObj, kObj, callback) {
                    if(process.env.overwrite_US != undefined && process.env.overwrite_US == "true"){
                        tcObj.User_Story = process.env.user_story;
                    }
                    queryUSTS(tcObj.User_Story, tcObj.ws, tcObj.proj, 'hierarchicalrequirement')
                        .then(function (resp) {
                            tcObj.User_Story = resp.id;
                            queryRH('', '')
                                .then(function(resp) {
                                    tcObj.owner = resp.owner_id;
                                    var obj = {tcObj:tcObj, kObj: kObj, error:error_message};
                                    createTC(obj, tcObj.ws, tcObj.proj)
                                        .then(function (response) {
                                            glb_test_case_id = response.id;
                                            response.json = json;response.i=i; response.j = tcObj.j;
                                            response.duration = kObj.duration; response.status = kObj.status;
                                            tcObj.glb_test_case_id = response.id;
                                            queryUSTS(tcObj.testset, tcObj.ws, tcObj.proj, 'testset')
                                                .then(function (resp) {
                                                    resp.status = stat;
                                                    resp.duration = duration1;
                                                    resp.i = i; resp.j = tcObj.j; resp.json = json;
                                                    updateTS(tcObj, resp)
                                                        .then(function (response) {
                                                            tcObj.last_run = false;
                                                            var RallyMethods = require('./RallyMethods.js');
                                                            TCR(tcObj, response)
                                                                .then( function(resp) {
                                                                    if (resp == 'step i')
                                                                        callback('step i');
                                                                    else if (resp == 'step j')
                                                                        callback('step j');
                                                                    else
                                                                        callback('callback');
                                                                });
                                                        }).catch(function(error){
                                                        callback('callback');
                                                    });
                                                }).catch(function(error){
                                                callback('callback');
                                            });
                                        }).catch(function(error){
                                        callback('callback');
                                    });
                                });
                        }).catch(function(error){
                        callback('callback');
                    });
                },
                /**
                 * Query Test Cases - contains method to call TestCaseFound and noTestCaseFound
                 * @param tpObj             object with TestSet, and length of json file
                 * @param response          Response from Query Test Folders (found, json, i,folderID, test_plan)
                 * @param callback          callback on error or when reach end of j loop ( test cases )
                 */
                TestFolderFound: function(tpObj, response, callback) {
                    json = response.json;
                    i = response.i;
                    glb_folder_id = response.id;
                    var step2 = function (j, done) {
                        if (j < response.json[response.i].elements.length) {
                            glb_j_length = response.json[response.i].elements.length;
                            test_case_name = response.json[response.i].elements[j].name;
                            temp = test_case_name.split(':');
                            if ((temp[1] != undefined)) {
                                User_Story = temp[0];
                                test_case_name = temp[1];
                            } else {
                                if (process.env.user_story != undefined)
                                    User_Story = process.env.user_story;
                                else User_Story = '';
                                //test_case_name = test_case_name.split(' ').join('_');
                            }
                            test_case_description = response.json[response.i].elements[j].description;
                            var test_case_line = response.json[response.i].elements[j].line;
                            var loop2 = function (j, done) {
                                var temp = 0;
                                queryTC('testcase', test_case_name, tpObj.proj, tpObj.ws)
                                    .then(function (resp) {
                                        glb_test_case_id = resp.id;
                                        var last_run = resp.last_run;
                                        glb_test_result_id = resp.test_case_result_id;
                                        if (resp != 'NOT_FOUND') {                                  // found test case
                                            resp.json = json; resp.i = i; resp.j = j;
                                            var tcObj = { User_Story: User_Story, resp: resp, j:j, test_case_name: test_case_name,
                                                test_case_description: test_case_description, glb_folder_id: glb_folder_id,
                                                build_num: build_num, testset: tpObj.testset, glb_test_case_id: glb_test_case_id,
                                                glb_test_result_id: glb_test_result_id, last_run: last_run, glb_i_length: tpObj.glb_i_length,
                                                glb_j_length: glb_j_length, i: i, ws:tpObj.ws, proj:tpObj.proj,
                                                testset_defined_env:tpObj.testset_defined_env, stepsArray:stepsArray };
                                            require('./RallyMethods.js').TestCaseFound(tcObj, function(response) {
                                                if(response == 'step i')
                                                    callback('step i');
                                                else if (response == 'step j')
                                                    step2(j + 1, done);
                                                else
                                                    callback('callback');
                                            });
                                        } else {                                                   // did not find test case
                                            resp = { json:json, i: i, j: j };
                                            var tcObj = { User_Story: User_Story, resp: resp, j:j, test_case_name: test_case_name,
                                                test_case_description: test_case_description, glb_folder_id: glb_folder_id,
                                                build_num: build_num, testset: tpObj.testset, glb_test_case_id: glb_test_case_id,
                                                glb_test_result_id: glb_test_result_id, last_run: last_run, glb_i_length: tpObj.glb_i_length,
                                                glb_j_length: glb_j_length, i: i, ws:tpObj.ws, proj:tpObj.proj,
                                                testset_defined_env:tpObj.testset_defined_env};
                                            kloop(tcObj)
                                                .then(function (response) {
                                                    var kObj = { duration: duration, status: stat, response:response, stepsArray:stepsArray };
                                                    tcObj.stepsArray = stepsArray;
                                                    require('./RallyMethods.js').noTestCaseFound(tcObj, kObj, function (response) {
                                                        if(response == 'step i')
                                                            callback('step i');
                                                        else if (response == 'step j')
                                                            step2(j + 1, done);
                                                        else
                                                            callback('callback');
                                                    });
                                                });
                                        }
                                    }).catch(function (error) {
                                    console.log('error: ' + error);
                                    callback();
                                });
                            };
                            loop2(j, done);
                        }
                    }
                    step2(0);
                },
                /**
                 * Create Test Folder, Test Case, & Test Case Result
                 * @param tpObj             object with TestSet, and length of json file
                 * @param response          Response from Query Test Folders (found, json, i,folderID, test_plan)
                 * @param callback          callback on error or when reach end of j loop ( test cases )
                 */
                noTestFolderFound: function(tpObj, response, callback) {
                    //console.log('no test folder found - creating');
                    json = response.json;
                    i = response.i;
                    var test_plan = response.test_plan;
                    var test_plan_description = response.json[response.i].description;
                    //test_plan = test_plan.split(' ').join('_');
                    createTP(test_plan, tpObj.ws, tpObj.proj)
                        .then(function (resp) {
                            resp.json = json; resp.i=i;
                            var step3 = function (j, done) {
                                if (j < resp.json[resp.i].elements.length) {
                                    glb_j_length = resp.json[resp.i].elements.length;
                                    glb_folder_id = resp.id;
                                    test_case_name = resp.json[resp.i].elements[j].name;
                                    temp = test_case_name.split(':');
                                    if ((temp[1] != undefined)) {
                                        User_Story = temp[0];
                                        test_case_name = temp[1];
                                    } else {
                                        if (process.env.user_story != undefined)
                                            User_Story = process.env.user_story;
                                        else User_Story = '';
                                        //test_case_name = test_case_name.split(' ').join('_');
                                    }
                                    test_case_description = json[resp.i].elements[j].description;
                                    var test_case_line = json[resp.i].elements[j].line;
                                    var tcObj = {User_Story: User_Story, test_case_name: test_case_name,
                                        test_case_description: test_case_description, glb_folder_id: resp.id, resp:resp,
                                        build_num: build_num, testset: tpObj.testset, glb_i_length: tpObj.glb_i_length,
                                        glb_j_length: glb_j_length, j:j, i:i, ws:tpObj.ws, proj:tpObj.proj,
                                        testset_defined_env:tpObj.testset_defined_env, stepsArray:stepsArray };
                                    var loop3 = function (j, done) {
                                        resp.j = j;
                                        kloop(tcObj)
                                            .then(function (resp1) {
                                                tcObj.stepsArray = stepsArray;
                                                var RallyMethods = require('./RallyMethods.js');
                                                var kObj = { duration: duration1, status: stat, response: resp1, stepsArray:stepsArray };
                                                RallyMethods.noTestCaseFound(tcObj, kObj, function (response) {
                                                    if (response == 'step i')
                                                        callback('step i');
                                                    else if (response == 'step j')
                                                        step3(j + 1, done);
                                                    else
                                                        callback('callback');
                                                });
                                            });
                                    };
                                    loop3(j, done);
                                }
                            };
                            step3(0);
                        });
                },
                /**
                 * Update Test Case Result, Create Test Case Result, or EOF
                 * @param tcObj             object w/  User_Story, resp, j, test_case_name, test_case_description, glb_folder_id,
                 * build_num, testset, glb_test_case_id, glb_test_result_id, last_run, glb_i_length, glb_j_length
                 * @param callback          callback on error or when reach end of j loop ( test cases )
                 */
                TestCaseResult: function(tcObj, resp, callback) {
                    if ((resp.status == undefined) || (resp.status == "undefined")) {
                        if ((resp.i == tcObj.glb_i_length - 1) && (resp.j == tcObj.glb_j_length - 1)) {
                            logger.info('Rally Results Posted');
                            console.log('Rally Results Posted');
                            callback('callback');
                        } else if ((resp.j == tcObj.glb_j_length - 1)) {
                            callback('step i');
                        } else {
                            callback('step j');
                        }
                    } else if ((tcObj.last_run == true)) {
                        //console.log('update test case result');
                        resp.duration = duration1; resp.status = stat;
                        var opts = {tcObj:tcObj, resp:resp};
                        updateTCR(opts, tcObj.ws, tcObj.proj)
                            .then(function (resp) {
                                if ((i == tcObj.glb_i_length - 1) && (tcObj.j == tcObj.glb_j_length - 1)) {
                                    logger.info('Rally Results Posted');
                                    console.log('Rally Results Posted');
                                    return callback('callback');
                                } else if ((tcObj.j == tcObj.glb_j_length - 1)) {
                                    callback('step i');
                                } else {
                                    callback('step j');
                                }
                            }).catch(function(error){
                            callback('callback');
                        });
                    } else {
                        //console.log('going to create test case result');
                        var opts = {tcObj:tcObj, resp:resp};
                        createTCR(opts, tcObj.ws, tcObj.proj)
                            .then(function (resp) {
                                resp.i = i; resp.j = tcObj.j;
                                if ((resp.i == tcObj.glb_i_length - 1) && (resp.j == tcObj.glb_j_length - 1)) {
                                    logger.info('Rally Results Posted');
                                    console.log('Rally Results Posted');
                                    return callback('callback');
                                } else if ((resp.j == tcObj.glb_j_length - 1)) {
                                    return callback('step i');
                                } else {
                                    return callback('step j');
                                }
                            }).catch(function (error) {
                            console.log('error: ' + error);
                            callback('callback'); //TODO: check if callback or continue iterating j
                        });
                    }
                }
            }
        };
        module.exports = new RallyMethods();
    }());