# Source: TestHelper.js

    /**
     * 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 () {

        'use strict';

        /**
         * Creates new TestHelper
         * @class TestHelper
         */
        var TestHelper = function () {
            var chai = require('chai');
            var TestHelperPO = require("./TestHelperPO.js");

            global.expect = chai.expect;
            global.should = chai.should();
            global.assert = chai.assert;
            chai.use(require('chai-as-promised'));
            var logger = require('./Logger.js');
            var EC = protractor.ExpectedConditions;
            var elementManager;
            var waitTime = 1000000;
            var drag = ("./drag.js");
            var dragFn = ('./dragFn.js');

            return {
                setWaitTime: function (wait) {
                    waitTime=wait;
                    console.log("Assigned wait time to: "+ wait);
                    logger.info("Assigned wait time to: "+ wait)
                },

                /**
                 * Assert if expected is included.
                 * @method getRandomString
                 * @returns {String}
                 */
                // To generate a random String name
                getRandomString: function () {
                    var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
                    var string_length = 8;
                    var randomstring = '';
                    for (var i = 0; i < string_length; i++) {
                        var rnum = Math.floor(Math.random() * chars.length);
                        randomstring += chars.substring(rnum, rnum + 1);
                    }
                    logger.info("Generated random string: " + randomstring)
                    return randomstring;
                },

                /**
                 * Assert if expected is included.
                 * @method assertInclude
                 * @param {object} actual
                 * @param {object} expected
                 * @param callbackOnError
                 * @returns {promise}
                 */

                assertInclude: function (actual, expected, callbackOnError) {
                    var error;
                    try {
                        logger.info('Asserting if actual: ' + actual + " is included in expected: " + expected + "\n");
                        assert.include(actual, expected)
                    } catch (e) {
                        error = e;
                        logger.info("Error on assertInclude: " + error);
                        if (callbackOnError) {
                            return callbackOnError(error)
                        }
                    }
                    return error
                },

                /**
                 * Assert if expected is equal to actual
                 * @param actual
                 * @param expected
                 * @param callbackOnError
                 * @returns {promise}
                 */
                assertEqual: function (actual, expected, callbackOnError) {
                    var error;
                    try {
                        logger.info('Asserting if actual: ' + actual + " is equal to expected: " + expected + "\n");
                        logger.info(assert.equal(actual, expected));
                        assert.equal(actual, expected);
                    } catch (e) {
                        error = e;
                        logger.info('Error in assertEqual: ' + error + "\n");
                        if (callbackOnError) {
                            callbackOnError(error)
                        }
                    }
                    return error;

                },

                /**
                 * Assert if something is True
                 * @param promise
                 * @param callbackOnError
                 * @returns {promise}
                 */
                assertTrue: function (promise, callbackOnError) {
                    var error;
                    try {
                        logger.info('Asserting if actual: ' + promise + " is equal to True \n");
                        assert.isTrue(promise);
                    } catch (e) {
                        error = e;
                        logger.info('Error in assertTrue: ' + error + "\n");
                        if (callbackOnError) {
                            callbackOnError(error)
                        }
                    }
                    return error;

                },
                /**
                 * Waits for all the angular content to load on the page
                 * @method waitForAngular
                 */
                waitForAngular: function () {
                    try {
                        browser.waitForAngular();
                    } catch (e) {
                        console.log("Ignoring Error ", e);
                        logger.info("Ignoring Error " + e + "\n");
                    }
                },
                /**
                 * An expectation to check if element is present on the DOM of a page and visible. **Can also provide element directly instead of the page,element of element repo**
                 * @method isElementPresent
                 * @param page {String} Page of element repository
                 * @param ele {string} Element name
                 * @return promise
                 */

                isElementPresent: function (page, ele) {

                    if (typeof page == "string") {
                        var locator = elementManager.findElement(page, ele)
                        return browser.wait(EC.visibilityOf(locator), waitTime).then(
                            function () {
                                logger.info("Found " + ele + "!\n");
                                return true;
                            },
                            function () {
                                return false;
                            })
                    }
                    else {
                        return browser.wait(EC.visibilityOf(page), waitTime, "false").then(function () {
                            // logger.info("Found " + ele.locator().value + "!\n");
                            return true
                        }, function () {
                            logger.info("Did not find: " + page.locator().value + "!\n");
                            return false
                        })
                    }
                },

                /**
                 * An expectation to check if element is NOT present on the DOM of a page or visible. **Can also provide element directly instead of the page,element of element repo**
                 * @method isElementNotPresent
                 * @param page {String} Page of element repository
                 * @param ele {string} Element name
                 * @return promise
                 */
                isElementNotPresent: function (page, ele) {
                    if (typeof page == "string") {
                        var locator = elementManager.findElement(page, ele)
                        return browser.wait(EC.not(EC.visibilityOf(locator)), waitTime).then(
                            function () {
                                logger.info("Found " + ele + "!\n");
                                return true;
                            },
                            function () {
                                return false;
                            })
                    }
                    else {
                        return browser.wait(EC.not(EC.visibilityOf(page)), waitTime, "false").then(function () {
                            // logger.info("Found " + ele.locator().value + "!\n");
                            return true
                        }, function () {
                            logger.info("Did not find: " + page.locator().value + "!\n");
                            return false
                        })
                    }
                },

                /**
                 * An expectation to check until element disappears. **Can also provide element directly instead of the page,element of element repo**
                 * @method waitForElementToDisappear
                 * @param page {String} Page of element repository
                 * @param ele {string} Element name
                 * @return promise
                 */

                waitForElementToDisappear: function (page, ele) {
                    if (typeof page == "string") {
                        var locator = elementManager.findElement(page, ele)
                        return browser.wait(EC.invisibilityOf(locator), waitTime).then(function () {
                                logger.info("Element " + ele + "disappeared!\n");
                                return true
                            },
                            function () {
                                return false;
                            })
                    }
                    else {
                        return browser.wait(EC.invisibilityOf(page), waitTime, "false").then(function () {
                                logger.info("Element " + ele + "disappeared!\n");
                                return true
                            },
                            function () {
                                return false;
                            })
                    }
                },

                /**
                 * An expectation to check if element is present on the DOM of a page and visible (same as isElementPresent
                 * but returns boolean) **Can also provide element directly instead of the page,element of element repo**
                 * @method isElementVisible
                 * @param {String} page
                 * @param {string} elementName
                 * @return boolean
                 */

                isElementVisible: function (page, ele) {
                    if (typeof page == "string") {
                        var locator = elementManager.findElement(page, ele)

                        return browser.wait(locator.isPresent(), waitTime).then(function (data) {
                            if (data === true) {
                                logger.info("Found " + ele + "!\n");
                                return browser.wait(locator.isDisplayed(), waitTime).then(function (isdisplayed) {
                                    if (isdisplayed) {
                                        logger.info("is Visible " + ele + "!\n")
                                        return isdisplayed
                                    } else {
                                        logger.info("not Visible " + ele + "!\n")
                                        return isdisplayed
                                    }

                                })
                            }
                            else {
                                logger.info("Not Found " + ele + "!\n");
                                return data
                            }
                        })
                    }
                    else {
                        return browser.wait(page.isPresent(), waitTime).then(function (data) {
                            if (data === true) {
                                logger.info("Found " + page.locator().value + "!\n");
                                return browser.wait(page.isDisplayed(), waitTime).then(function (isdisplayed) {
                                    if (isdisplayed) {
                                        logger.info("is Visible " + page.locator().value + "!\n")
                                        return isdisplayed
                                    } else {
                                        logger.info("not Visible " + page.locator().value + "!\n")
                                        return isdisplayed
                                    }

                                })
                            }
                            else {
                                logger.info("Not Found " + page.locator().value + "!\n");
                                return data
                            }
                        })
                    }
                },

                /**
                 * An Expectation for checking an element is visible and enabled such that you can click it. **Can also provide element directly instead of the page,element of element repo**
                 * @method elementToBeClickable
                 * @param {String} page
                 * @param {string} elementName
                 * @returns {promise}
                 */
                /*elementToBeClickable: function (page, element) {
                 var locator = elementManager.findElement(page, element);

                 return browser.wait(function () {
                 return locator.click().then(
                 function () {
                 logger.info("Clicked on" + element + "!\n");
                 return true;
                 },w
                 function () {
                 logger.info(element + " Not Clickable!\n");
                 return false;
                 });
                 }, waitTime);
                 },*/

                elementToBeClickable: function (page, ele) {
                    if (typeof page == "string") {
                        var locator = elementManager.findElement(page, ele);

                        return browser.wait(function () {
                            return locator.click().then(
                                function () {
                                    logger.info("Clicked on" + ele + "!\n");
                                    return true;
                                },
                                function () {
                                    // logger.info(ele + " Not Clickable!\n");
                                    return false;
                                });
                        }, waitTime);
                    }
                    else {
                        return browser.wait(function () {
                            return page.click().then(function () {
                                logger.info("Clicked on " + page.locator().value + "!\n");
                                return true
                            }, function () {
                                // logger.info(ele.locator().value + " Not Clickable!\n");
                                return false
                            })
                        }, waitTime)
                    }
                },

                /**
                 * Checks for the element to be present and then sends keys. **Can also provide element directly instead of the page,element of element repo**
                 * @method sendKeys
                 * @param {String} page
                 * @param {String} element
                 * @param {String} text
                 */
                sendKeys: function (page, ele, text) {
                    if (typeof page == "string") {
                        return this.isElementPresent(page, ele).then(function () {
                            var locator = elementManager.findElement(page, ele);
                            logger.info("Sending Keys to " + ele + ": '" + text + "'")
                            return locator.sendKeys(text);
                        });
                    }
                    else {
                        return this.isElementPresent(page).then(function () {
                            logger.info("Sending Keys to " + page.locator().value + ": '" + ele + "'")
                            return page.sendKeys(ele)
                        })
                    }
                },

                /**
                 * Checks for the element to be present and then gets text. **Can also provide element directly instead of the page,element of element repo**
                 * @method getText
                 * @param {String} page
                 * @param {String} element
                 */
                getText: function (page, ele) {
                    if (typeof page == "string") {
                        return this.isElementPresent(page, ele).then(function () {
                            var locator = elementManager.findElement(page, ele);
                            return locator.getText().then(function (text) {
                                logger.info("Text Value of " + ele + ": " + text)
                                return text
                            })
                        });
                    }
                    else {
                        return this.isElementPresent(page).then(function () {
                            return page.getText().then(function (text) {
                                logger.info("Text Value of " + page.locator().value + ": " + text)
                                return text;
                            })
                        })
                    }
                },

                /**
                 * Expect an alert to be present.
                 * @method alertIsPresent
                 * @returns {promise}
                 */
                alertsIsPresent: function () {

                    return browser.wait(EC.alertIsPresent(), waitTime);
                },

                /**
                 * Accepts alert dialog box
                 * @method acceptAlert
                 */

                acceptAlert: function () {
                    return browser.switchTo().alert().accept();
                },

                /**
                 * Dismisses alert dialog box
                 * @method dismissAlert
                 */

                dismissAlert: function () {
                    return browser.switchTo().alert().dismiss();
                },

                /**
                 * An expectation for checking if the given text is present in the element. **Can also provide element directly instead of the page,element of element repo**
                 * @method textToBePresentInElement
                 * @param {String} page
                 * @param {string} elementName
                 * @param {string} text
                 * @returns {promise}
                 */
                textToBePresentInElement: function (page, element, text) {
                    if (typeof page == "string") {
                        var locator = elementManager.findElement(page, element)
                        return browser.wait(EC.textToBePresentInElement(locator, text), waitTime).then(
                            function () {
                                logger.info(text + " is present in " + element + "!\n");
                                return true;
                            },
                            function () {
                                logger.info(text + " is NOT present in " + element + "!\n");
                                return false;
                            });
                    }
                    else {
                        return browser.wait(EC.textToBePresentInElement(page, element), waitTime).then(function () {
                            logger.info(element + " is present in " + page.locator().value + "!\n");
                            return true
                        }, function () {
                            logger.info(element + " is NOT present in " + page.locator().value + "!\n");
                            return false
                        })
                    }
                },

                /**
                 * An expectation for checking if the given text is present in the element’s value. **Can also provide element directly instead of the page,element of element repo**
                 * @method textToBePresentInElementValue
                 * @param {String} page
                 * @param {string} elementName
                 * @param {string} text
                 * @returns {promise}
                 */
                textToBePresentInElementValue: function (page, element, text) {
                    if (typeof page == "string") {
                        var locator = elementManager.findElement(page, element);
                        return browser.wait(EC.textToBePresentInElementValue(locator, text), waitTime).then(
                            function () {
                                logger.info(text + " is present in " + element + "'s value!\n");
                                return true;
                            },
                            function () {
                                logger.info(text + " is NOT present in " + element + "'s value!\n");
                                return false;
                            });
                    }
                    else {
                        return browser.wait(EC.textToBePresentInElementValue(page, element), waitTime).then(function () {
                            logger.info(element + " is present in " + page.locator().value + "'s value!\n");
                            return true
                        }, function () {
                            logger.info(element + " is NOT present in " + page.locator().value + "'s value!\n");
                            return false
                        })
                    }
                },

                /**
                 * Checks to see if element is selected. **Can also provide element directly instead of the page,element of element repo**
                 * @method elementToBeSelected
                 * @param {string} page
                 * @param {string} element
                 * @returns {promise}
                 */
                elementToBeSelected: function (page, element) {
                    if (typeof page == "string") {
                        var locator = elementManager.findElement(page, element);
                        return browser.wait(EC.elementToBeSelected(locator), waitTime).then(
                            function () {
                                logger.info(element + " is selected!\n");
                                return true;
                            },
                            function () {
                                logger.info(element + " is NOT selected!\n");
                                return false;
                            });
                    }
                    else {
                        return browser.wait(EC.elementToBeSelected(page), waitTime).then(function () {
                            logger.info(page.locator().value + " is selected!\n");
                            return true
                        }, function () {
                            logger.info(page.locator().value + " is NOT selected!\n");
                            return false
                        })
                    }
                },

                /**
                 * An expectation for checking that the title contains a case-sensitive substring.
                 * @method titleContains
                 * @param {string} text
                 * @returns {promise}
                 */
                titleContains: function (text) {
                    return browser.wait(EC.titleContains(text), waitTime);
                },

                /**
                 * An expectation for checking the title of a page.
                 * @method titleIs
                 * @param {string} text
                 * @returns {promise}
                 */
                titleIs: function (text) {

                    return browser.wait(EC.titleIs(text), waitTime);
                },

                /**
                 * Sets the element manager
                 * @method setElementManager
                 * @param {Object} eM
                 */
                setElementManager: function (eM) {
                    elementManager = eM;
                },

                /**
                 * Gets the element manager
                 * @method getElementManager
                 * @return {Object}
                 */
                getElementManager: function () {
                    return elementManager;
                },

                /**
                 * Uploads file in upload dialog box
                 * @method uploadFile
                 * @param {String} filePath
                 */

                uploadFile: function (filePath) {
                    var absolutePath = path.resolve(__dirname, filePath);
                    var a = $('input[type="file"]');
                    fs.stat(absolutePath, function (err, stat) {
                        if (err == null) {
                            logger.info("File exists");
                            console.log("File exists");
                            a.sendKeys(absolutePath)
                            logger.info("File Uploaded");
                        } else if (err.code == "ENOENT") {
                            logger.info("File does not exist!");
                            console.error("File does not exist!")
                        } else {
                            logger.info("Some other error: ", err.code);
                            console.log("Some other error: ", err.code);
                        }
                    })
                },
                /**
                 * Switches to specific iFrame
                 * @method iFrameSwitch
                 * @param {String} page
                 * @param {String} element
                 */
                iFrameSwitch: function (page, element) {
                    if (typeof page == "string") {
                        return this.isElementPresent(page, element).then(function () {
                            elementManager.browserFindElement(page, element).then(function (ele) {
                                browser.switchTo().frame(ele).then(function () {
                                    logger.info("Switched over to " + ele + "iFrame");
                                });
                            })
                        })
                    }
                },
                /**
                 * Scrolls until the element is in view. **Can also provide element directly instead of the page,element of element repo**
                 * @method scrollIntoView
                 * @param {String} page
                 * @param {String} element
                 */
                scrollIntoView: function (page, element) {
                    if (typeof page == "string") {
                        return this.isElementPresent(page, element).then(function () {
                            var locator = elementManager.findElement(page, element);
                            browser.executeScript('arguments[0].scrollIntoView()', locator.getWebElement()).then(function () {
                                logger.info("Scrolled to " + element + "\n")
                            })
                        })
                    }
                    else {
                        return this.isElementPresent(page).then(function () {
                            browser.executeScript("arguments[0].scrollIntoView()", page.getWebElement()).then(function () {
                                logger.info("Scrolled to " + page.locator().value + "\n")
                            })
                        })
                    }
                },

                /**
                 * Drags and drops element to specified location. **Can also provide element directly instead of the page,element of element repo**
                 * @method dragAndDrop
                 * @param {String} dragPage
                 * @param {String} dragElement
                 * @param {String} dropPage
                 * @param {String} dropElement
                 */

                dragAndDrop: function (dragPage, dragElement, dropPage, dropElement) {
                    if (typeof page == "string") {
                        return this.isElementPresent(dragPage, dragElement).then(function () {
                            var dragLocator = elementManager.findElement(dragPage, dragElement);
                            var dropLocator = elementManager.findElement(dropPage, dropElement);
                            dragLocator.getAttribute("draggable").then(function (isDragable) {
                                if (isDragable != null) {
                                    browser.executeScript(drag, dragLocator.getWebElement(), dropLocator.getWebElement()).then(function () {
                                        logger.info("Dragged " + dragElement + " to " + dropElement)
                                    })
                                } else {
                                    browser.executeScript(dragFn, dragLocator.getWebElement(), dropLocator.getWebElement()).then(function () {
                                        logger.info("Dragged " + dragElement + " to " + dropElement)
                                        browser.actions().mouseMove(dropLocator).mouseUp().perform();
                                    })
                                }
                            })
                        });
                    }
                    else {
                        return this.isElementPresent(dragPage).then(function () {
                            dragPage.getAttribute("draggable").then(function (isDragable) {
                                if (isDragable != null) {
                                    browser.executeScript(drag, dragPage.getWebElement(), dragElement.getWebElement()).then(function () {
                                        logger.info("Dragged " + dragPage.locator().value + " to " + dragElement.locator().value)
                                    })
                                } else {
                                    browser.executeScript(dragFn, dragPage.getWebElement(), dragElement.getWebElement()).then(function () {
                                        logger.info("Dragged " + dragPage.locator().value + " to " + dragElement.locator().value)
                                        browser.actions().mouseMove(dragElement).mouseUp().perform();
                                    })
                                }
                            })
                        });
                    }
                },

                /**
                 * Drags and drops element to specified location. **Can also provide element directly instead of the page,element of element repo**
                 * @method dragAndDrop2
                 * @param {String} dragPage
                 * @param {String} dragElement
                 * @param {String} dropPage
                 * @param {String} dropElement
                 */

                dragAndDrop2: function (dragPage, dragElement, dropPage, dropElement) {
                    if (typeof page == "string") {
                        return this.isElementPresent(dragPage, dragElement).then(function () {
                            var dragLocator = elementManager.findElement(dragPage, dragElement);
                            var dropLocator = elementManager.findElement(dropPage, dropElement);
                            browser.actions().dragAndDrop(dragLocator, dropLocator).mouseUp().perform()
                        });
                    }
                    else {
                        return this.isElementPresent(dragPage).then(function () {
                            browser.actions().dragAndDrop(dragPage, dragElement).mouseUp().perform()
                        })
                    }
                },

                /**
                 * Gets attribute value of specified element. **Can also provide element directly instead of the page,element of element repo**
                 * @method getAttribute
                 * @param {String} page
                 * @param {String} element
                 * @param {String} attribute
                 */

                getAttribute: function (page, element, attribute) {
                    if (typeof page == "string") {
                        console.log("inside here 22")
                        return this.isElementPresent(page, element).then(function () {
                            var locator = elementManager.findElement(page, element);
                            return locator.getAttribute(attribute).then(function (attributeText) {
                                logger.info(element + "'s attribute " + attribute + ": " + attributeText)
                                return attributeText;
                            });
                        });
                    }
                    else {
                        return this.isElementPresent(page).then(function () {
                            return page.getAttribute(element).then(function (attributeText) {
                                logger.info(page.locator().value + "'s attribute " + element + ": " + attributeText)
                                return attributeText;
                            })
                        });
                    }
                },

                /**
                 * Gets css value of specified element. **Can also provide element directly instead of the page,element of element repo**
                 * @method getCssValue
                 * @param {String} page
                 * @param {String} element
                 * @param {String} cssAttribute
                 */

                getCssValue: function (page, element, cssAttribute) {
                    if (typeof page == "string") {
                        return this.isElementPresent(page, element).then(function () {
                            var locator = elementManager.findElement(page, element);
                            return locator.getCssValue(cssAttribute).then(function (cssTextValue) {
                                logger.info(element + "'s CSS Value " + cssAttribute + ": " + cssTextValue)
                                return cssTextValue;
                            })
                        });
                    }
                    else {
                        return this.isElementPresent(page).then(function () {
                            return page.getCssValue(element).then(function (cssTextValue) {
                                logger.info(page.locator().value + "'s CSS Value " + element + ": " + cssTextValue)
                                return cssTextValue
                            })
                        });
                    }
                },

                /**
                 * Logs in the GE SSO page. (Default username and password are provided) Parameters are optional
                 * @method geSSOLogin
                 * @param {String} username
                 * @param {String} password
                 */

                geSSOLogin: function (username, password) {

                    var userName;
                    var passWord;

                    if (typeof username != "undefined")
                        userName = username
                    else
                        userName = "502641091"
                    if (typeof password != "undefined")
                        passWord = password
                    else
                        passWord = "Aut0mati0n"
                    return TestHelperPO.isElementPresent(element(by.id("username"))).then(function () {
                        element(by.id("username")).sendKeys(userName);
                        element(by.id("password")).sendKeys(passWord);
                        element(by.id("password")).sendKeys(protractor.Key.ENTER);
                        logger.info("Logged in GE SSO Page")
                    })
                }

            }
        }

        module.exports = new TestHelper();

    }())