/*
 * 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.
 */
var fs = require('fs');
var path = require('path');
var collectFiles = require('./collect-files');
var copyProps = require('./copy-props');
var writeModule = require('./write-module');
var writeScript = require('./write-script');
var licensePath = path.join(__dirname, '..', 'templates', 'LICENSE-for-js-file.txt');
var pkgJson = require('../../package.json');

module.exports = function bundle (platform, debug, commitId, platformVersion, platformPath) {
    var modules = collectFiles(path.join('src', 'common'));
    var scripts = collectFiles(path.join('src', 'scripts'));
    modules[''] = path.join('src', 'cordova.js');

    // check to see if platform has cordova-js-src directory
    if (fs.existsSync(platformPath) && fs.existsSync(path.join(platformPath, 'cordova-js-src'))) {
        copyProps(modules, collectFiles(path.join(platformPath, 'cordova-js-src')));
    } else {
        // for platforms that don't have a release with cordova-js-src yet
        // or if platform === test
        if (platform === 'test') {
            copyProps(modules, collectFiles(path.join('src', 'legacy-exec', platform)));
        } else {
            console.log('Your version of ' + platform + ' does not contain cordova-js-src. Update to a newer version of ' + platform + '.');
            throw 'Stopped process';
        }
    }
    // test doesn't support custom paths
    if (platform === 'test') {
        var androidPath = path.resolve(pkgJson['cordova-platforms']['cordova-android']);
        var iosPath = path.resolve(pkgJson['cordova-platforms']['cordova-ios']);
        var testFilesPath = path.resolve(androidPath, 'cordova-js-src', 'android');
        // Add android platform-specific modules that have tests to the test bundle.
        if (fs.existsSync(androidPath)) {
            modules['android/exec'] = path.resolve(androidPath, 'cordova-js-src', 'exec.js');
        } else {
            // testFilesPath = path.resolve('src', 'legacy-exec', 'android', 'android');
            // modules['android/exec'] = path.resolve('src', 'legacy-exec', 'android', 'exec.js');
            console.log('Couldn\'t add android test files.');
            throw 'Stopped process';
        }
        copyProps(modules, collectFiles(testFilesPath, 'android'));

        // Add iOS platform-specific modules that have tests for the test bundle.
        if (fs.existsSync(iosPath)) {
            modules['ios/exec'] = path.join(iosPath, 'cordova-js-src', 'exec.js');
        } else {
            // modules['ios/exec'] = path.join('src', 'legacy-exec', 'ios', 'exec.js');
            console.log('Couldn\'t add iOS test files.');
            throw 'Stopped process';
        }
    }

    var output = [];

    output.push('// Platform: ' + platform);
    output.push('// ' + commitId);

    // write header
    output.push('/*', fs.readFileSync(licensePath, 'utf8'), '*/');
    output.push(';(function() {');

    output.push("var PLATFORM_VERSION_BUILD_LABEL = '" + platformVersion + "';");

    // write initial scripts
    if (!scripts['require']) {
        throw new Error("didn't find a script for 'require'");
    }

    writeScript(output, scripts['require'], debug);

    // write modules
    var moduleIds = Object.keys(modules);
    moduleIds.sort();

    for (var i = 0; i < moduleIds.length; i++) {
        var moduleId = moduleIds[i];

        writeModule(output, modules[moduleId], moduleId, debug);
    }

    output.push("window.cordova = require('cordova');");

    // write final scripts
    if (!scripts['bootstrap']) {
        throw new Error("didn't find a script for 'bootstrap'");
    }

    writeScript(output, scripts['bootstrap'], debug);

    var bootstrapPlatform = 'bootstrap-' + platform;
    if (scripts[bootstrapPlatform]) {
        writeScript(output, scripts[bootstrapPlatform], debug);
    }

    // write trailer
    output.push('})();');

    return output.join('\n');
};
