/*
    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('node:fs');
const path = require('node: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.cpSync(defaultConfigPath, ownConfigPath, { recursive: true });
    } else if (fs.existsSync(ownConfigPath)) {
        this.events.emit('verbose', `Generating defaults.xml from own config.xml for platform "${this.platform}"`);
        fs.cpSync(ownConfigPath, defaultConfigPath, { recursive: true });
    } else {
        this.events.emit('verbose', `case 3 "${this.platform}"`);
        fs.cpSync(sourceCfg.path, ownConfigPath, { recursive: true });
    }

    // 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.cpSync(srcManifestPath, manifestPath, { recursive: true });
    } else {
        this.events.emit('verbose', `Creating new manifest file in => ${this.path}`);

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

    (new PackageJsonParser(this.locations.www, cordovaProject.root))
        .configure(this.config)
        .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 => { // eslint-disable-line array-callback-return
        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.cpSync(path.join(rootDir, elementKeys[0]), value, { recursive: true });
        }
    });
}
