/*
 *
 * 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.
 *
*/

/*global __coverage__: true*/

var path             = require('path');
var fs               = require('fs');
var collect          = require('./collect');
var istanbul         = require('istanbul');
var mkdirp           = require('mkdirp');
var jas              = require('jasmine-node');
var testLibName      = path.join(__dirname, '..', '..', 'pkg', 'cordova.test.js');
var testLib          = fs.readFileSync(testLibName, 'utf8');

var jsdom    = require("jsdom-nogyp").jsdom;
var document = jsdom(null, null, { url: 'file:///jsdomtest.info/a?b#c' });
var window   = document.createWindow();

module.exports = function(callback) {

    console.log('starting node-based tests');

    // put jasmine in scope
    Object.keys(jas).forEach(function (key) {
        this[key] = window[key] = global[key] = jas[key];
    });

    // Hack to fix jsdom with node v0.11.13+
    delete String.prototype.normalize;

    try {
        // instrument loaded cordova.js before it will be loaded into DOM
        var instrumenter = new istanbul.Instrumenter();
        var generatedCode = instrumenter.instrumentSync(testLib);

        eval(generatedCode);
    }
    catch (e) {
        console.log("error eval()ing " + testLibName + ": " + e);
        console.log(e.stack);
        throw e;
    }

    // hijack require
    require = window.cordova.require;
    define  = window.cordova.define;

    // load in our tests
    var tests = [];
    collect(path.join(__dirname, '..', '..', 'test'), tests);
    for (var x in tests) {
        eval(fs.readFileSync(tests[x], "utf-8"));
    }

    var env = jasmine.getEnv();
    env.addReporter(new jas.TerminalReporter({
        color: true,
        onComplete: function(runner) {

            // Check that global __coverage__ variable
            // defined by istanbul is defined and not empty
            if (__coverage__ || Object.keys(__coverage__).length === 0) {

                var config = istanbul.config.loadObject(istanbul.config.defaultConfig());
                var reportingDir = config.reporting.dir();
                
                mkdirp.sync(reportingDir);

                var file = path.resolve(reportingDir, 'coverage.json'),
                    collector = new istanbul.Collector(config),
                    reporter = new istanbul.Reporter(config);

                console.error('=============================================================================');
                console.error('Writing coverage object [' + file + ']');

                // regular expression is necessary to replace filename in report object
                // generated by istanbul (smth. like "14843508345.js") with real filename
                var correctFilenameRe = new RegExp(Object.keys(__coverage__)[0], "g");
                var report = JSON.stringify(__coverage__).replace(correctFilenameRe, testLibName.replace(/\\/g, '\\\\'));

                fs.writeFileSync(file, report, 'utf8');
                collector.add(JSON.parse(report));

                console.error('Writing coverage reports at [' + path.resolve(reportingDir) + ']');
                console.error('=============================================================================');
                
                reporter.addAll(["lcov", "text"]);
                reporter.write(collector, true, function (win) {
                    callback(runner.results().passed());
                });
            } else {
                console.error('No coverage information was collected, exit without writing coverage information');
                callback(runner.results().passed());
            }
        }
    }));

    console.log("------------");
    console.log("Unit Tests:");
    env.execute();
};