/*
 * 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.
*/
module.exports = function(grunt) {
    var childProcess = require('child_process');
    var fs = require('fs');
    var path = require('path');

    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        cordovajs: {
          "android": {},
          "blackberry10": {},
          "ios": {},
          "osx": {},
          "test": {},
          "windows8": { useWindowsLineEndings: true },
          "windowsphone": { useWindowsLineEndings: true },
        },
        clean: ['pkg'],
        jshint: {
            options: {
                jshintrc: '.jshintrc',
            },
            src: [ 'lib/**/*.js' ]
        },
    });

    // Iterates over a directory
    function forEachFile(root, cbFile, cbDone) {
        var count = 0;

        function scan(name) {
            ++count;

            fs.stat(name, function (err, stats) {
                if (err) cbFile(err);

                if (stats.isDirectory()) {
                    fs.readdir(name, function (err, files) {
                        if (err) cbFile(err);

                        files.forEach(function (file) {
                            scan(path.join(name, file));
                        });
                        done();
                    });
                } else if (stats.isFile()) {
                    cbFile(null, name, stats, done);
                } else {
                    done();
                }
            });
        }

        function done() {
            --count;
            if (count === 0 && cbDone) cbDone();
        }

        scan(root);
    }

    function processWhiteSpace(processor, callback) {
        var rexp_minified = new RegExp("\\.min\\.js$");
        var rexp_src = new RegExp('\\.js$');
        forEachFile('lib', function(err, file, stats, cbDone) {
            //if (err) throw err;
            if (rexp_minified.test(file) || !rexp_src.test(file)) {
                cbDone();
            } else {
                var origsrc = src = fs.readFileSync(file, 'utf8');

                // tabs -> four spaces
                if (src.indexOf('\t') >= 0) {
                    src = src.split('\t').join('    ');
                }

                // eliminate trailing white space
                src = src.replace(/ +\n/g, '\n');

                if (origsrc !== src) {
                    // write it out yo
                    processor(file, src);
                }
                cbDone();
            }
        }, callback);
    }

    grunt.registerMultiTask('cordovajs', 'Packages cordova.js', function() {
        var packager = require("./build/packager");
        var done = this.async();
        var platformName = this.target;
        var useWindowsLineEndings = this.data.useWindowsLineEndings;
        packager.generate(platformName, useWindowsLineEndings, done);
    });

    grunt.registerTask('_test', 'Runs test in node', function() {
        var done = this.async();
        require('./test/runner').node(done);
    });

    grunt.registerTask('_btest', 'Runs tests in the browser', function() {
        require('./test/runner').browser();
        this.async(); // never finish.
    });

    grunt.registerTask('_complainwhitespace', 'Complain about what fixwhitespace would fix', function() {
        var done = this.async();
        var complainedAboutWhitespace = false;
        processWhiteSpace(function(file, newSource) {
            if (!complainedAboutWhitespace) {
                grunt.log.writeln("files with whitespace issues: (to fix: `grunt fixwhitespace`)");
                complainedAboutWhitespace = true;
            }
            grunt.log.writeln("   " + file);
        }, done);
    });

    grunt.registerTask('_fixwhitespace', 'Converts tabs to four spaces, eliminates trailing white space, converts newlines to proper form - enforcing style guide ftw!', function() {
        var done = this.async();
        var complainedAboutWhitespace = false;
        processWhiteSpace(function(file, newSource) {
            if (!complainedAboutWhitespace) {
                grunt.log.writeln("Fixed whitespace issues in:");
                complainedAboutWhitespace = true;
            }
            fs.writeFileSync(file, newSource, 'utf8');
            grunt.log.writeln("   " + file);
        }, done);
    });

    // TODO - Delete this task and use Grunt's built-in jshint (CB-3964).
    grunt.registerTask('_hint', 'Runs jshint.', function() {
        var done = this.async();
        var knownWarnings = [
            "Redefinition of 'FileReader'",
            "Redefinition of 'require'",
            "Read only",
            "Redefinition of 'console'"
        ];
        var filterKnownWarnings = function(el, index, array) {
            var wut = true;
            // filter out the known warnings listed out above
            knownWarnings.forEach(function(e) {
                wut = wut && (el.indexOf(e) == -1);
            });
            wut = wut && (!el.match(/\d+ errors/));
            return wut;
        };

        childProcess.exec("jshint lib", function(err,stdout,stderr) {
            var exs = stdout.split('\n');
            grunt.log.writeln(exs.filter(filterKnownWarnings).join('\n'));
            done();
        });
    });
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-jshint');

    // Default task(s).
    grunt.registerTask('build', ['cordovajs', '_hint', '_complainwhitespace']);
    grunt.registerTask('default', ['build', '_test']);
    grunt.registerTask('test', ['build', '_test']);
    grunt.registerTask('btest', ['build', '_btest']);
};

@@ -1294,32 +1294,58 @@
 ndings: true %7D,%0A
+          %22firefoxos%22: %7B%7D%0A
         %7D,%0A     

add firefoxos to gruntfile