/*
    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 fs = require('fs-extra');
const path = require('path');
const { ConfigParser, xmlHelpers, events, CordovaError } = require('cordova-common');
const ManifestJsonParser = require('./ManifestJsonParser');
const PackageJsonParser = require('./PackageJsonParser');
const SettingJsonParser = require('./SettingJsonParser');

module.exports.prepare = function (cordovaProject, options) {
    // First cleanup current config and merge project's one into own
    const defaultConfigPath = path.join(this.locations.platformRootDir, 'cordova', 'defaults.xml');
    const ownConfigPath = this.locations.configXml;
    const sourceCfg = cordovaProject.projectConfig;

    // If defaults.xml is present, overwrite platform config.xml with it.
    // Otherwise save whatever is there as defaults so it can be
    // restored or copy project config into platform if none exists.
    if (fs.existsSync(defaultConfigPath)) {
        this.events.emit('verbose', `Generating config.xml from defaults for platform "${this.platform}"`);
        fs.copySync(defaultConfigPath, ownConfigPath);
    } else if (fs.existsSync(ownConfigPath)) {
        this.events.emit('verbose', `Generating defaults.xml from own config.xml for platform "${this.platform}"`);
        fs.copySync(ownConfigPath, defaultConfigPath);
    } else {
        this.events.emit('verbose', `case 3 "${this.platform}"`);
        fs.copySync(sourceCfg.path, ownConfigPath);
    }

    // merge our configs
    this.config = new ConfigParser(ownConfigPath);
    xmlHelpers.mergeXml(sourceCfg.doc.getroot(), this.config.doc.getroot(), this.platform, true);
    this.config.write();

    // Update own www dir with project's www assets and plugins' assets and js-files
    this.parser.update_www(cordovaProject, this.locations);
    // Update icons
    updateIcons(cordovaProject, this.locations);
    // Update splash screens
    updateSplashScreens(cordovaProject, this.config, this.locations);

    // Copy or Create manifest.json
    const srcManifestPath = path.join(cordovaProject.locations.www, 'manifest.json');
    if (fs.existsSync(srcManifestPath)) {
        // just blindly copy it to our output/www
        // todo: validate it? ensure all properties we expect exist?
        const manifestPath = path.join(this.locations.www, 'manifest.json');
        this.events.emit('verbose', `Copying ${srcManifestPath} => ${manifestPath}`);
        fs.copySync(srcManifestPath, manifestPath);
    } else {
        this.events.emit('verbose', `Creating new manifest file in => ${this.path}`);

        (new ManifestJsonParser(this.locations.www))
            .configure(this.config)
            .write();
    }

    const projectPackageJson = JSON.parse(fs.readFileSync(path.join(cordovaProject.root, 'package.json'), 'utf8'));

    (new PackageJsonParser(this.locations.www, cordovaProject.root))
        .configure(this.config, projectPackageJson)
        .enableDevTools(options && options.options && !options.options.release)
        .write();

    const userElectronSettings = cordovaProject.projectConfig.getPlatformPreference('ElectronSettingsFilePath', 'electron');
    const userElectronSettingsPath = userElectronSettings && fs.existsSync(path.resolve(cordovaProject.root, userElectronSettings))
        ? path.resolve(cordovaProject.root, userElectronSettings)
        : undefined;

    // update Electron settings in .json file
    (new SettingJsonParser(this.locations.www))
        .configure(this.config, options.options, userElectronSettingsPath)
        .write();

    // update project according to config.xml changes.
    return this.parser.update_project(this.config, options);
};

/**
 * Update Electron Splash Screen image.
 */
function updateSplashScreens (cordovaProject, config, locations) {
    const splashScreens = cordovaProject.projectConfig.getSplashScreens('electron');

    // Skip if there are no splash screens defined in config.xml
    if (!splashScreens.length) {
        events.emit('verbose', 'This app does not have splash screens defined.');
        return;
    }

    const splashScreen = prepareSplashScreens(splashScreens);
    const resourceMap = createResourceMap(cordovaProject, locations, splashScreen);

    updatePathToSplashScreen(config, locations, resourceMap);

    events.emit('verbose', 'Updating splash screens');
    copyResources(cordovaProject.root, resourceMap);
}

/**
 *  Get splashScreen image. Choose only one image, if the user provided multiple.
 */
function prepareSplashScreens (splashScreens) {
    let splashScreen;
    // choose one icon for a target
    const chooseOne = (defaultSplash, splash) => {
        events.emit('verbose', `Found extra splash screen image: ${defaultSplash.src} and ignoring in favor of ${splash.src}.`);

        defaultSplash = splash;

        return defaultSplash;
    };

    // iterate over remaining icon elements to find the icons for the app and installer
    for (const image of splashScreens) {
        image.extension = path.extname(image.src);
        splashScreen = splashScreen ? chooseOne(splashScreen, image) : image;
    }

    return { splashScreen };
}

/**
 *  Update path to Splash Screen in the config.xml
 */
function updatePathToSplashScreen (config, locations, resourceMap) {
    const elementKeys = Object.keys(resourceMap[0]);
    const splashScreenPath = resourceMap[0][elementKeys];
    const splash = config.doc.find('splash');
    const preferences = config.doc.findall('preference');

    splash.attrib.src = path.relative(locations.www, splashScreenPath);
    for (const preference of preferences) {
        if (preference.attrib.name === 'SplashScreen') {
            preference.attrib.value = splash.attrib.src;
        }
    }
    config.write();
}

/**
 * Update Electron App and Installer icons.
 */
function updateIcons (cordovaProject, locations) {
    const icons = cordovaProject.projectConfig.getIcons('electron');

    // Skip if there are no app defined icons in config.xml
    if (!icons.length) {
        events.emit('verbose', 'This app does not have icons defined');
        return;
    }

    const filteredIcons = icons.filter(icon => checkIconsAttributes(icon));

    if (!filteredIcons.length) {
        throw new CordovaError('No icon match the required size. Please ensure that ".png" icon is at least 512x512 and has a src attribute.');
    }

    const chosenIcons = prepareIcons(filteredIcons);
    const resourceMap = createResourceMap(cordovaProject, locations, chosenIcons);

    events.emit('verbose', 'Updating icons');
    copyResources(cordovaProject.root, resourceMap);
}

/**
 * Check if all required attributes are set.
 */
function checkIconsAttributes (icon) {
    if (((icon.height && icon.width) >= 512 || (icon.height && icon.width) === undefined) && icon.src) return true;

    events.emit('info', `The following${icon.target ? ` ${icon.target}` : ''} icon with a size of width=${icon.width} height=${icon.height} does not meet the requirements and will be ignored.`);
    return false;
}

/**
 *  Find and select icons for the app and installer.
 *  Also, set high resolution icons, if provided by a user.
 */
function prepareIcons (icons) {
    let customIcon;
    let appIcon;
    let installerIcon;

    // choose one icon for a target
    const chooseOne = (defaultIcon, icon) => {
        events.emit('verbose', `Found extra icon for target ${icon.target}: ${defaultIcon.src} and ignoring in favor of ${icon.src}.`);

        defaultIcon = icon;

        return defaultIcon;
    };

    // find if there is high resolution images that has DPI suffix
    const highResAndRemainingIcons = findHighResIcons(icons);
    const highResIcons = highResAndRemainingIcons.highResIcons;
    const remainingIcons = highResAndRemainingIcons.remainingIcons;

    // iterate over remaining icon elements to find the icons for the app and installer
    for (const icon of remainingIcons) {
        const size = icon.width || icon.height;
        icon.extension = path.extname(icon.src);

        switch (icon.target) {
        case 'app':
            appIcon = appIcon ? chooseOne(appIcon, icon) : icon;
            break;
        case 'installer':
            installerIcon = installerIcon ? chooseOne(installerIcon, icon) : icon;
            break;
        case undefined:
            if ((size >= 512 || size === undefined) && !Object.keys(highResIcons).length) {
                customIcon = customIcon ? chooseOne(customIcon, icon) : icon;
            }
            break;
        }
    }

    return { customIcon, appIcon, installerIcon, highResIcons };
}

/**
 *  Find and high resolution icons and return remaining icons,
 *  unless an icon has a specified target.
 */
function findHighResIcons (icons) {
    // find icons that are not in the highResIcons, unless they have a target set
    const findRemainingIcons = (icons, highResIcons) => icons.filter(
        (icon) => (icon.target || (!icon.target && !highResIcons.includes(icon)))
            ? Object.assign(icon)
            : false
    );

    const highResIcons = icons.filter(icon => {
        if (icon.src.includes('@')) {
            const extension = path.extname(icon.src);
            const suffix = icon.src.split('@').pop().slice(0, -extension.length);

            return Object.assign(icon, { suffix, extension });
        }
    });

    let remainingIcons = findRemainingIcons(icons, highResIcons);
    // set normal image that has standard resolution
    const has1x = highResIcons.find(obj => obj.suffix === '1x');
    if (!has1x && Object.keys(highResIcons).length) {
        const highResIcon = highResIcons[Object.keys(highResIcons)[0]];
        let baseIcon = remainingIcons.find(obj => obj.src === highResIcon.src.split('@')[0] + highResIcon.extension);

        if (!baseIcon) {
            throw new CordovaError('Base icon for high resolution images was not found.');
        }

        const extension = path.extname(baseIcon.src);
        const suffix = '1x';

        baseIcon = Object.assign(baseIcon, { suffix, extension });

        highResIcons.push(baseIcon);

        remainingIcons = findRemainingIcons(icons, highResIcons);
    }

    return { highResIcons, remainingIcons };
}

/**
 * Map resources to the appropriate target directory and name.
 */
function createResourceMap (cordovaProject, locations, resources) {
    const resourceMap = [];

    for (const key in resources) {
        const resource = resources[key];

        if (!resource) {
            continue;
        }

        let targetPath;
        switch (key) {
        case 'customIcon':
            // Copy icon for the App
            targetPath = path.join(locations.www, 'img', `app${resource.extension}`);
            resourceMap.push(mapResources(cordovaProject.root, resource.src, targetPath));
            // Copy icon for the Installer
            targetPath = path.join(locations.buildRes, `installer${resource.extension}`);
            resourceMap.push(mapResources(cordovaProject.root, resource.src, targetPath));
            break;
        case 'appIcon':
            targetPath = path.join(locations.www, 'img', `app${resource.extension}`);
            resourceMap.push(mapResources(cordovaProject.root, resource.src, targetPath));
            break;
        case 'installerIcon':
            targetPath = path.join(locations.buildRes, `installer${resource.extension}`);
            resourceMap.push(mapResources(cordovaProject.root, resource.src, targetPath));
            break;
        case 'highResIcons':
            for (const key in resource) {
                const highResIcon = resource[key];
                targetPath = path.join(locations.www, 'img', 'icon');
                targetPath += highResIcon.suffix === '1x' ? highResIcon.extension : `@${highResIcon.suffix}${highResIcon.extension}`;
                resourceMap.push(mapResources(cordovaProject.root, highResIcon.src, targetPath));
            }
            break;
        case 'splashScreen':
            targetPath = path.join(locations.www, '.cdv', `splashScreen${resource.extension}`);
            resourceMap.push(mapResources(cordovaProject.root, resource.src, targetPath));
            break;
        }
    }
    return resourceMap;
}

/**
 * Get a map containing resources of a specified name (or directory) to the target directory.
 */
function mapResources (rootDir, sourcePath, targetPath) {
    return fs.existsSync(path.join(rootDir, sourcePath))
        ? { [sourcePath]: targetPath }
        : {};
}

/**
 * Copy resources to the target destination according to the resource map.
 */
function copyResources (rootDir, resourceMap) {
    resourceMap.forEach(element => {
        const elementKeys = Object.keys(element);

        if (elementKeys.length) {
            const value = elementKeys.map((e) => element[e])[0];
            fs.copySync(path.join(rootDir, elementKeys[0]), value);
        }
    });
}
