/*
    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 { events } = require('cordova-common');

class PackageJsonParser {
    constructor (wwwDir, projectRootDir) {
        this.path = path.join(wwwDir, 'package.json');
        this.www = wwwDir;
        this.projectRootDir = projectRootDir;
        this.package = {
            main: 'cdv-electron-main.js'
        };
    }

    configure (config, projectPackageJson) {
        if (config) {
            this.package.name = config.packageName() || 'io.cordova.hellocordova';
            this.package.displayName = config.name() || 'HelloCordova';
            this.package.version = config.version() || '1.0.0';
            this.package.description = config.description() || 'A sample Apache Cordova application that responds to the deviceready event.';

            if (projectPackageJson.dependencies) {
                const cordovaDependencies = [];
                const droppedPackages = [];

                for (const [npmPackage, npmPackageValue] of Object.entries(projectPackageJson.dependencies)) {
                    if (/^cordova(?!-plugin)-/.test(npmPackage)) {
                        cordovaDependencies.push(npmPackage);
                    }

                    // Format FilePath Based Dependencies
                    if (npmPackageValue.startsWith('file:..')) {
                        const relativePath = npmPackageValue.split('file:')[1];
                        const absolutePath = path.resolve(this.projectRootDir, relativePath);

                        if (fs.pathExistsSync(absolutePath)) {
                            projectPackageJson.dependencies[npmPackage] = `file:${absolutePath}`;
                        } else {
                            droppedPackages.push(npmPackage);
                        }
                    }
                }

                // If Cordova dependencies are detected in "dependencies" of "package.json" warn for potential app package bloating
                if (cordovaDependencies.length) {
                    events.emit('warn', '[Cordova Electron] The built package size may be larger than necessary. Please run with --verbose for more details.');

                    events.emit('verbose', `[Cordova Electron] The following Cordova package(s) were detected as "dependencies" in the projects "package.json" file.
\t- ${cordovaDependencies.join('\n\t- ')}

It is recommended that all Cordova packages are defined as "devDependencies" in the "package.json" file. It is safe to move them manually.
Packages defined as a dependency will be bundled with the application and can increase the built application's size.
`);
                }

                if (droppedPackages.length) {
                    events.emit('warn', `[Cordova Electron] The following local npm dependencies could not be located and will not be deployed to the Electron app:\n\t${droppedPackages.join('\n\t- ')}`);
                }

                this.package.dependencies = projectPackageJson.dependencies;
            }

            this.configureHomepage(config);
            this.configureLicense(config);

            if (config.doc.find('author').attrib.email) {
                this.package.author = {
                    name: config.author() || 'Apache Cordova Team',
                    email: config.doc.find('author').attrib.email
                };
            } else {
                this.package.author = config.author() || 'Apache Cordova Team';
            }
        }

        return this;
    }

    configureHomepage (config) {
        this.package.homepage = (config.doc.find('author') && config.doc.find('author').attrib.href) || 'https://cordova.io';
    }

    configureLicense (config) {
        this.package.license = (config.doc.find('license') && config.doc.find('license').text && config.doc.find('license').text.trim()) || 'Apache-2.0';
    }

    write () {
        fs.writeFileSync(this.path, JSON.stringify(this.package, null, 2), 'utf8');
    }
}

module.exports = PackageJsonParser;
