const fs = require('mz/fs');
const JSZip = require('jszip');
const path = require('path');
const semver = require('semver');
const { parseChangelogMarkdown } = require('./changelogMarkdownParser');

function readInfoFromComposerJson(composerJsonString) {
    const composerJson = JSON.parse(composerJsonString);

    return {
        version: composerJson.version,
        shopwareCompatibility: composerJson.require['shopware/core'],
        label: {
            en: composerJson.extra.label['en-GB'],
            de: composerJson.extra.label['de-DE'],
        },
    };
}

function readInfoFromPluginJson(pluginJsonString) {
    const pluginJson = JSON.parse(pluginJsonString);
    const minimumVersion = pluginJson.compatibility.minimumVersion || '0.0.0';
    const maximumVersion = pluginJson.compatibility.maximumVersion || '99.99.99';

    return {
        version: pluginJson.currentVersion,
        shopwareCompatibility: `${minimumVersion} - ${maximumVersion}`,
        label: pluginJson.label,
    };
}

module.exports = class Plugin {
    static async readFromZipFile(zipFilePath) {
        if (!await fs.exists(zipFilePath)) {
            throw new Error(`File ${zipFilePath} does not exist`);
        }

        const data = await fs.readFile(zipFilePath);
        const zip = await JSZip.loadAsync(data);

        const sw5RootDirectory = zip.folder(/^(Backend|Frontend|Core)\/\w+\//)[0];
        const sw6RootDirectory = zip.folder(/^\w+\//)[0];

        const plugin = new Plugin();
        let rootDirectory;
        if (sw5RootDirectory) {
            rootDirectory = sw5RootDirectory.name;
            plugin.technicalName = rootDirectory.split('/')[1];
            plugin.shopwareMajorVersion = 5;
            Object.assign(plugin, readInfoFromPluginJson(
                await zip.file(path.join(rootDirectory, 'plugin.json')).async('string'),
            ));
        } else if (sw6RootDirectory) {
            rootDirectory = sw6RootDirectory.name;
            plugin.technicalName = rootDirectory.split('/')[0];
            plugin.shopwareMajorVersion = 6;
            Object.assign(plugin, readInfoFromComposerJson(
                await zip.file(path.join(rootDirectory, 'composer.json')).async('string'),
            ));
        } else {
            throw new Error('Could not detect whether plugin targets Shopware 5 or Shopware 6.');
        }

        const parsedChangelog = parseChangelogMarkdown(
            await zip.file(path.join(rootDirectory, 'CHANGELOG.md')).async('string'),
        );
        plugin.releaseNotes = parsedChangelog[plugin.version];

        return plugin;
    }

    isCompatibleWithShopwareVersion(shopwareVersion) {
        return semver.satisfies(shopwareVersion, this.shopwareCompatibility);
    }
};

@@ -2653,24 +2653,33 @@
 ion(shopware
+Marketing
 Version) %7B%0A 
@@ -2689,75 +2689,1674 @@
     
-return semver.satisfies(shopwareVersion, this.shopwareCompatibility
+if (!shopwareMarketingVersion) %7B%0A            return false;%0A        %7D%0A%0A        if (this.shopwareMajorVersion === 6) %7B%0A            if (!shopwareMarketingVersion.startsWith('6.')) %7B%0A                return false;%0A            %7D%0A%0A            const shopwareVersion = this.getShopware6Semver(shopwareMarketingVersion);%0A            const pluginShopwareCompatibility = this.getShopware6Semver(this.shopwareCompatibility);%0A%0A            return semver.satisfies(shopwareVersion, pluginShopwareCompatibility);%0A        %7D%0A%0A        if (this.shopwareMajorVersion === 5) %7B%0A            if (!shopwareMarketingVersion.startsWith('5.')) %7B%0A                return false;%0A            %7D%0A%0A            return semver.satisfies(shopwareMarketingVersion, this.shopwareCompatibility);%0A        %7D%0A%0A        throw new Error(%0A            'The scs-commander is incompatible with the given Shopware version number'%0A            + %60 ($%7BshopwareMarketingVersion%7D).%60,%0A        );%0A    %7D%0A%0A    getShopware6Semver(version) %7B%0A        if (!version.startsWith('6.')) %7B%0A            throw new Error(%60%22$%7Bversion%7D%22 is not a valid Shopware 6 version number.%60);%0A        %7D%0A%0A        const numberOfVersionComponents = version.split('.').length;%0A        if (numberOfVersionComponents === 4) %7B%0A            // %22New%22, 4-component version (e.g. %606.3.0.0%60). Hence just drop the first component.%0A            return version.substring(2);%0A        %7D%0A%0A        if (numberOfVersionComponents === 3) %7B%0A            // Legacy version (e.g. %606.1.0%60). Hence drop the first component and add a patch version of %600%60.%0A            return %60$%7Bversion.substring(2)%7D.0%60;%0A        %7D%0A%0A        throw new Error('The given shopware version format is unknown.'
 );%0A 

Add compatibility with Shopware's new 4-digit version numbers (#34)