/*
    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)
        .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);
        }
    });
}
