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

const child_process = require('child_process');
const xml2js = require('xml2js');
const VulcanControlLib = require('../build/Release/VulcanControlLib.node').VulcanControlAdapter;
const parser = new xml2js.Parser({ async: false, explicitArray: false });
const opn = require('opn');

class VulcanControlAdapter extends VulcanControlLib {
    getInstalledApps(topLevelOnly = true, onlyVisibleProducts = true) {
        let json;
        parser.parseString(this._getInstalledApps(topLevelOnly), (err, result) => {
            if (err) {
                throw err;
            }
            json = result;
        });

        return json.ProductsInfo.ProductInfo
            .filter(({ IsVisibleProduct }) => !onlyVisibleProducts || IsVisibleProduct === 'true')
            .map(({ SAPCode, CodexVersion, BuildVersion, LaunchString }) => ({ SAPCode, CodexVersion, BuildVersion, LaunchString }));
    }

    isAppInstalled(sapCode) {
        return this.getInstalledApps(false, false).some(({ SAPCode }) => sapCode === SAPCode);
    }

    getAppDetails(sapCode) {
        return this.getInstalledApps(false, false).filter(({ SAPCode }) => sapCode === SAPCode);
    }

    launchApp(sapCode, setFocus, cmdLineArgs) {
        if (sapCode && sapCode.startsWith('SPRK')) {
            opn(`adbxd://${cmdLineArgs || ''}`);
            return Promise.resolve(true);
        }
        return new Promise((resolve, reject) => {
            this._launchApp(sapCode, setFocus, cmdLineArgs, (err, status) => {
                if (err) {
                    return reject(err);
                }
                resolve(status);
            });
        });
    }

    _getXDDetails() {
        const cmdToRun = 'tasklist /fo csv /fi "IMAGENAME eq XD.exe" /nh';
        let result = child_process.execSync(cmdToRun);
        if (result instanceof Buffer) {
            result = result.toString();
        }
        return result.split(',').map(val => val.slice(1, -1));
    }

    isAppRunning(sapCode) {
        // Vulcan doesn't support UWP apps as of now - testing whether XD is running on Windows
        // is fragile, so we always return true until we get support from VulcanControlLib
        if (process.platform !== 'darwin' && sapCode && sapCode.startsWith('SPRK')) {
            return true;
        }
        return this._isAppRunning(sapCode);
    }

    getProcessId(sapCode) {
        // Vulcan doesn't support UWP apps as of now, putting in this workaround
        // to get information by running tasklist command on windows.
        if (process.platform !== 'darwin' && sapCode && sapCode.startsWith('SPRK')) {
            const result = this._getXDDetails();
            if (result.length > 1 && result[0] === 'XD.exe') {
                return parseInt(result[1]);
            }
            return 0;
        }
        return this._getProcessId(sapCode);
    }
}

module.exports = VulcanControlAdapter;
