/**
    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 cp = require('child_process');
const shell = require('shelljs');
const Server = require('./LocalServer');
const path = require('path');
const Q = require('q');
const fs = require('fs');
const { logger, exec, execPromise, utilities } = require('./utils');
const Reporters = require('./Reporters');
const ParamedicKill = require('./ParamedicKill');
const AppiumRunner = require('./appium/AppiumRunner');
const ParamedicLogCollector = require('./ParamedicLogCollector');
const ParamediciOSPermissions = require('./ParamediciOSPermissions');
const ParamedicTargetChooser = require('./ParamedicTargetChooser');
const ParamedicAppUninstall = require('./ParamedicAppUninstall');
const ParamedicApp = require('./ParamedicApp');
const ParamedicSauceLabs = require('./ParamedicSauceLabs');

// this will add custom promise chain methods to the driver prototype
require('./appium/helpers/wdHelper');

// Time to wait for initial device connection.
// If device has not connected within this interval the tests are stopped.
const INITIAL_CONNECTION_TIMEOUT = 540000; // 9mins

Q.longStackSupport = true;

class ParamedicRunner {
    constructor (config) {
        this.tempFolder = null;
        this.config = config;
        this.targetObj = undefined;
        this.paramedicSauceLabs = null;

        this.isBrowser = this.config.getPlatformId() === utilities.BROWSER;
        this.isWindows = this.config.getPlatformId() === utilities.WINDOWS;
        this.isIos = this.config.getPlatformId() === utilities.IOS;

        exec.setVerboseLevel(config.isVerbose());
    }

    run () {
        let isTestPassed = false; // eslint-disable-line

        this.checkConfig();

        return Q().then(() => {
            // create project and prepare (install plugins, setup test startpage, install platform, check platform requirements)
            const paramedicApp = new ParamedicApp(this.config, this.storedCWD, this);
            this.tempFolder = paramedicApp.createTempProject();
            shell.pushd(this.tempFolder.name);
            return paramedicApp.prepareProjectToRunTests();
        })
            .then(() => {
                if (this.config.runMainTests()) {
                // start server
                    const noListener = (this.isBrowser) && this.config.shouldUseSauce();
                    return Server.startServer(this.config.getPorts(), this.config.getExternalServerUrl(), this.config.getUseTunnel(), noListener);
                }
            })
            .then((server) => {
                if (this.config.runMainTests()) {
                    // configure server usage
                    this.server = server;

                    this.injectReporters();
                    this.subcribeForEvents();

                    const logUrl = this.server.getConnectionUrl(this.config.getPlatformId());
                    this.writeMedicJson(logUrl);

                    logger.normal('Start building app and running tests at ' + (new Date()).toLocaleTimeString());
                }
                // run tests
                return this.runTests();
            })
            .timeout(this.config.getTimeout(), 'Timed out after waiting for ' + this.config.getTimeout() + ' ms.')
            .catch((error) => {
                logger.error(error);
                console.log(error.stack);
                throw new Error(error);
            })
            .fin((result) => {
                logger.warn('---------------------------------------------------------');
                logger.warn('6. Collect data and clean up');
                logger.warn('---------------------------------------------------------');

                isTestPassed = result;
                logger.normal('Completed tests at ' + (new Date()).toLocaleTimeString());

                // If we run --shouldUseSauce immedatly fetch and return Sauce details.
                if (this.config.shouldUseSauce()) {
                    return this.paramedicSauceLabs.displaySauceDetails.apply(this.paramedicSauceLabs, [this.sauceBuildName]); // eslint-disable-line
                }

                // When --shouldUseSauce and --justbuild is not set, fetch logs from the device.
                if (this.config.getAction() !== 'build') {
                // collect logs and uninstall app
                    this.collectDeviceLogs();
                    return this.uninstallApp()
                        .fail(() => { /* do not fail if uninstall fails */ })
                        .fin(() => {
                            this.killEmulatorProcess();
                        });
                }

                // --justbuild does nothing.
                return Q.resolve();
            })
            .fin(() => {
                this.cleanUpProject();
            });
    }

    checkConfig () {
        logger.warn('---------------------------------------------------------');
        logger.warn('0. Paramedic config');
        var config = this.config.getAll();
        for (var property in config) {
            if (config.hasOwnProperty(property)) {
                if (typeof config[property] !== 'undefined' && config[property] !== null) {
                    logger.warn(`   - ${property}: ${config[property]}`);
                }
            }
        }
        logger.warn('---------------------------------------------------------');

        if (this.config.shouldUseSauce()) {
            this.paramedicSauceLabs = new ParamedicSauceLabs(this.config, this);
            this.paramedicSauceLabs.checkSauceRequirements.apply(this.paramedicSauceLabs);
        }
        if (!this.config.runMainTests() && !this.config.runAppiumTests()) {
            throw new Error('No tests to run: both --skipAppiumTests and --skipMainTests are used');
        }

        if (!['cordova', 'phonegap'].includes(this.config.getCli())) {
            if (!path.isAbsolute(this.config.getCli())) {
                const cliAbsolutePath = path.resolve(this.config.getCli());
                this.config.setCli(cliAbsolutePath);
            }
        }

        logger.info('cordova-paramedic: Will use the following cli: ' + this.config.getCli());
    }

    setPermissions () {
        const applicationsToGrantPermission = ['kTCCServiceAddressBook'];
        if (this.isIos) {
            logger.info('cordova-paramedic: Setting required permissions.');
            const tccDb = this.config.getTccDb();
            if (tccDb) {
                const appName = utilities.PARAMEDIC_DEFAULT_APP_NAME;
                const paramediciOSPermissions = new ParamediciOSPermissions(appName, tccDb, this.targetObj);
                paramediciOSPermissions.updatePermissions(applicationsToGrantPermission);
            }
        }
    }

    injectReporters () {
        const reporters = Reporters.getReporters(this.config.getOutputDir());

        [
            'jasmineStarted',
            'specStarted',
            'specDone',
            'suiteStarted',
            'suiteDone',
            'jasmineDone'
        ].forEach((route) => {
            reporters.forEach((reporter) => {
                if (reporter[route] instanceof Function) {
                    this.server.on(route, reporter[route].bind(reporter));
                }
            });
        });
    }

    subcribeForEvents () {
        this.server.on('deviceLog', (data) => {
            logger.verbose('device|console.' + data.type + ': ' + data.msg[0]);
        });

        this.server.on('deviceInfo', (data) => {
            logger.normal('cordova-paramedic: Device info: ' + JSON.stringify(data));
        });
    }

    writeMedicJson (logUrl) {
        logger.normal('cordova-paramedic: writing medic log url to project ' + logUrl);
        fs.writeFileSync(path.join('www', 'medic.json'), JSON.stringify({ logurl: logUrl }));
    }

    maybeRunFileTransferServer () {
        return Q().then(() => {
            const plugins = this.config.getPlugins();
            for (let i = 0; i < plugins.length; i++) {
                if (plugins[i].indexOf('cordova-plugin-file-transfer') >= 0 && !this.config.getFileTransferServer() && !this.config.isCI()) {
                    return this.server.startFileTransferServer(this.tempFolder.name);
                }
            }
        });
    }

    runLocalTests () {
        logger.warn('... locally');
        logger.warn('---------------------------------------------------------');

        let runProcess = null;

        // checking for Android platform here because in this case we still need to start an emulator
        // will check again a bit lower
        if (!this.config.runMainTests() && this.config.getPlatformId() !== utilities.ANDROID) {
            logger.normal('Skipping main tests...');
            return Q(utilities.TEST_PASSED);
        }

        logger.info('cordova-paramedic: running tests locally');

        return Q()
            .then(() => this.maybeRunFileTransferServer())
            .then(() => this.getCommandForStartingTests())
            .then((command) => {
                this.setPermissions();

                return Q.all([
                    Q().then(() => {
                        logger.normal('cordova-paramedic: running command ' + command);

                        if (this.config.getPlatformId() !== utilities.BROWSER) {
                            return execPromise(command);
                        }
                        console.log('$ ' + command);

                        // a precaution not to try to kill some other process
                        runProcess = cp.exec(command, () => {
                            runProcess = null;
                        });
                    }),
                    Q().then(() => {
                        // skipping here and not at the beginning because we need to
                        // start up the Android emulator for Appium tests to run on
                        if (!this.config.runMainTests()) {
                            logger.normal('Skipping main tests...');
                            return utilities.TEST_PASSED;
                        }

                        // skip tests if it was just build
                        if (this.shouldWaitForTestResult()) {
                            return Q.promise((resolve, reject) => {
                            // reject if timed out
                                this.waitForConnection().catch(reject);
                                // resolve if got results
                                this.waitForTests().then(resolve);
                            });
                        }

                        return utilities.TEST_PASSED; // if we're not waiting for a test result, just report tests as passed
                    })
                ]);

            })
            .then((results) => {
                return results[1];
            })
            .fin((result) => {
                return runProcess
                    ? Q.Promise((resolve) => {
                        utilities.killProcess(runProcess.pid, () => {
                            resolve(result);
                        });
                    })
                    : result;
            });
    }

    runAppiumTests (useSauce) {
        logger.warn('---------------------------------------------------------');
        logger.warn('5. Run Appium tests');
        logger.warn('---------------------------------------------------------');

        const platform = this.config.getPlatformId();
        logger.normal('Start running Appium tests...');

        if (this.config.getAction() === 'build') {
            logger.normal('Skipping Appium tests: action = build ...');
            return Q(utilities.TEST_PASSED);
        }
        if (!this.config.runAppiumTests()) {
            logger.normal('Skipping Appium tests: not configured to run ...');
            return Q(utilities.TEST_PASSED);
        }
        if (platform !== utilities.ANDROID && platform !== utilities.IOS) {
            logger.warn('Unsupported platform for Appium test run: ' + platform);
            // just skip Appium tests
            return Q(utilities.TEST_PASSED);
        }
        if (!useSauce && (!this.targetObj || !this.targetObj.target)) {
            throw new Error('Cannot determine local device name for Appium');
        }

        logger.normal('Running Appium tests ' + (useSauce ? 'on Sauce Labs' : 'locally'));

        let options = {
            platform: platform,
            appPath: this.tempFolder.name,
            pluginRepos: this.config.getPlugins().map(plugin => path.join(this.tempFolder.name, 'plugins', path.basename(plugin))),
            appiumDeviceName: this.targetObj && this.targetObj.target,
            udid: this.targetObj && this.targetObj.simId,
            appiumPlatformVersion: null,
            screenshotPath: path.join(process.cwd(), 'appium_screenshots'),
            output: this.config.getOutputDir(),
            verbose: this.config.isVerbose(),
            sauce: useSauce,
            cli: this.config.getCli()
        };

        if (useSauce) {
            options.sauceAppPath = 'sauce-storage:' + this.paramedicSauceLabs.getAppName.apply(this.paramedicSauceLabs);
            options.sauceUser = this.config.getSauceUser();
            options.sauceKey = this.config.getSauceKey();
            options.sauceCaps = this.paramedicSauceLabs.getSauceCaps.apply(this.paramedicSauceLabs);
            options.sauceCaps.name += '_Appium';
        }

        const appiumRunner = new AppiumRunner(options);
        if (appiumRunner.options.testPaths && appiumRunner.options.testPaths.length === 0) {
            logger.warn('Couldn\'t find Appium tests, skipping...');
            return Q(utilities.TEST_PASSED);
        }

        return Q()
            .then(() => appiumRunner.prepareApp())
            .then(() => {
                if (useSauce) {
                    return this.paramedicSauceLabs.packageApp.apply(this.paramedicSauceLabs)
                        .then(() => this.paramedicSauceLabs.uploadApp.apply(this.paramedicSauceLabs));
                }
            })
            .then(() => appiumRunner.runTests(useSauce));
    }

    runTests () {
        let isTestPassed = false;

        logger.warn('---------------------------------------------------------');
        logger.warn('4. Run (Jasmine) tests...');

        // Sauce Labs
        if (this.config.shouldUseSauce()) {
            return this.paramedicSauceLabs.runSauceTests.apply(this.paramedicSauceLabs)
                .then((result) => {
                    isTestPassed = result;
                })
                .then(() => this.runAppiumTests(true))
                .then(isAppiumTestPassed => isTestPassed === utilities.TEST_PASSED && isAppiumTestPassed === utilities.TEST_PASSED);
        // Not Sauce Labs
        } else {
            return this.runLocalTests()
                .then((result) => {
                    isTestPassed = result;
                })
                .then(() => this.runAppiumTests())
                .then(isAppiumTestPassed => isTestPassed === utilities.TEST_PASSED && isAppiumTestPassed === utilities.TEST_PASSED);
        }
    }

    waitForTests () {
        logger.info('cordova-paramedic: waiting for test results');
        return Q.promise((resolve, reject) => {

            // time out if connection takes too long
            const ERR_MSG = 'waitForTests: Seems like device not connected to local server in ' + INITIAL_CONNECTION_TIMEOUT / 1000 + ' secs';
            setTimeout(() => {
                if (!this.server.isDeviceConnected()) {
                    reject(new Error(ERR_MSG));
                }
            }, INITIAL_CONNECTION_TIMEOUT);

            this.server.on('jasmineDone', (data) => {
                logger.info('cordova-paramedic: tests have been completed');

                // Is Test Passed
                resolve((data.specResults.specFailed === 0));
            });

            this.server.on('disconnect', () => {
                reject(new Error('Device is disconnected before passing the tests'));
            });
        });
    }

    getCommandForStartingTests () {
        let cmd = [
            this.config.getCli(),
            this.config.getAction(),
            this.config.getPlatformId()
        ]
            .concat(utilities.PARAMEDIC_COMMON_ARGS)
            .concat([this.config.getArgs()]);

        if (this.isBrowser) {
            return cmd.join(' ');
        } else if (this.config.getAction() === 'build' || (this.isWindows && this.config.getArgs().indexOf('appx=8.1-phone') < 0)) {
            // The app is to be run as a store app or just build. So no need to choose a target.
            return Q(cmd.join(' '));
        }

        // For now we always trying to run test app on emulator
        return new ParamedicTargetChooser(this.tempFolder.name, this.config).chooseTarget(
            true, // useEmulator
            this.config.getTarget() // preferredTarget
        ).then(targetObj => {
            this.targetObj = targetObj;

            return cmd
                .concat(['--target', `"${this.targetObj.target}"`])
                // CB-11472 In case of iOS provide additional '--emulator' flag, otherwise
                // 'cordova run ios --target' would hang waiting for device with name
                // as specified in 'target' in case if any device is physically connected
                .concat(this.isIos ? ['--emulator'] : [])
                .join(' ');
        });
    }

    shouldWaitForTestResult () {
        const action = this.config.getAction();
        return (action.indexOf('run') === 0) || (action.indexOf('emulate') === 0);
    }

    waitForConnection () {
        const ERR_MSG = 'waitForConnection: Seems like device not connected to local server in ' + INITIAL_CONNECTION_TIMEOUT / 1000 + ' secs';

        return Q.promise((resolve, reject) => {
            setTimeout(() => {
                if (!this.server.isDeviceConnected()) {
                    reject(new Error(ERR_MSG));
                } else {
                    resolve();
                }
            }, INITIAL_CONNECTION_TIMEOUT);
        });
    }

    cleanUpProject () {
        this.server && this.server.cleanUp();
        if (this.config.shouldCleanUpAfterRun()) {
            logger.info('cordova-paramedic: Deleting the application: ' + this.tempFolder.name);
            shell.popd();
            shell.rm('-rf', this.tempFolder.name);
        }
    }

    killEmulatorProcess () {
        if (this.config.shouldCleanUpAfterRun()) {
            logger.info('cordova-paramedic: Killing the emulator process.');
            const paramedicKill = new ParamedicKill(this.config.getPlatformId());
            paramedicKill.kill();
        }
    }

    collectDeviceLogs () {
        logger.info('Collecting logs for the devices.');
        const outputDir = this.config.getOutputDir() ? this.config.getOutputDir() : this.tempFolder.name;
        const logMins = this.config.getLogMins() ? this.config.getLogMins() : utilities.DEFAULT_LOG_TIME;
        const paramedicLogCollector = new ParamedicLogCollector(this.config.getPlatformId(), this.tempFolder.name, outputDir, this.targetObj);
        paramedicLogCollector.collectLogs(logMins);
    }

    uninstallApp () {
        logger.info('Uninstalling the app.');
        const paramedicAppUninstall = new ParamedicAppUninstall(this.tempFolder.name, this.config.getPlatformId());
        return paramedicAppUninstall.uninstallApp(this.targetObj, utilities.PARAMEDIC_DEFAULT_APP_NAME);
    }
}

let storedCWD = null;

exports.run = function (paramedicConfig) {
    storedCWD = storedCWD || process.cwd();

    const runner = new ParamedicRunner(paramedicConfig, null);
    runner.storedCWD = storedCWD;

    return runner.run();
};
