/*
 Copyright (c) 2012, Yahoo! Inc.  All rights reserved.
 Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
 */

/**
 * utility methods to process coverage objects. A coverage object has the following
 * format.
 *
 *      {
 *          "/path/to/file1.js": { file1 coverage },
 *          "/path/to/file2.js": { file2 coverage }
 *      }
 *
 *  The internals of the file coverage object are intentionally not documented since
 *  it is not a public interface.
 *
 *  *Note:* When a method of this module has the word `File` in it, it will accept
 *  one of the sub-objects of the main coverage object as an argument. Other
 *  methods accept the higher level coverage object with multiple keys.
 *
 * Works on `node` as well as the browser.
 *
 * Usage on nodejs
 * ---------------
 *
 *      var objectUtils = require('istanbul').utils;
 *
 * Usage in a browser
 * ------------------
 *
 * Load this file using a `script` tag or other means. This will set `window.coverageUtils`
 * to this module's exports.
 *
 * @class ObjectUtils
 * @module main
 * @static
 */
(function (isNode) {
    /**
     * adds line coverage information to a file coverage object, reverse-engineering
     * it from statement coverage. The object passed in is updated in place.
     *
     * Note that if line coverage information is already present in the object,
     * it is not recomputed.
     *
     * @method addDerivedInfoForFile
     * @static
     * @param {Object} fileCoverage the coverage object for a single file
     */
    function addDerivedInfoForFile(fileCoverage) {
        var statementMap = fileCoverage.statementMap,
            statements = fileCoverage.s,
            lineMap;

        if (!fileCoverage.l) {
            fileCoverage.l = lineMap = {};
            Object.keys(statements).forEach(function (st) {
                var line = statementMap[st].start.line,
                    count = statements[st],
                    prevVal = lineMap[line];
                if (count === 0 && statementMap[st].skip) { count = 1; }
                if (typeof prevVal === 'undefined' || prevVal < count) {
                    lineMap[line] = count;
                }
            });
        }
    }
    /**
     * adds line coverage information to all file coverage objects.
     *
     * @method addDerivedInfo
     * @static
     * @param {Object} coverage the coverage object
     */
    function addDerivedInfo(coverage) {
        Object.keys(coverage).forEach(function (k) {
            addDerivedInfoForFile(coverage[k]);
        });
    }
    /**
     * removes line coverage information from all file coverage objects
     * @method removeDerivedInfo
     * @static
     * @param {Object} coverage the coverage object
     */
    function removeDerivedInfo(coverage) {
        Object.keys(coverage).forEach(function (k) {
            delete coverage[k].l;
        });
    }

    function percent(covered, total) {
        var tmp;
        if (total > 0) {
            tmp = 1000 * 100 * covered / total + 5;
            return Math.floor(tmp / 10) / 100;
        } else {
            return 100.00;
        }
    }

    function computeSimpleTotals(fileCoverage, property, mapProperty) {
        var stats = fileCoverage[property],
            map = mapProperty ? fileCoverage[mapProperty] : null,
            ret = { total: 0, covered: 0, skipped: 0 };

        Object.keys(stats).forEach(function (key) {
            var covered = !!stats[key],
                skipped = map && map[key].skip;
            ret.total += 1;
            if (covered || skipped) {
                ret.covered += 1;
            }
            if (!covered && skipped) {
                ret.skipped += 1;
            }
        });
        ret.pct = percent(ret.covered, ret.total);
        return ret;
    }

    function computeBranchTotals(fileCoverage) {
        var stats = fileCoverage.b,
            branchMap = fileCoverage.branchMap,
            ret = { total: 0, covered: 0, skipped: 0 };

        Object.keys(stats).forEach(function (key) {
            var branches = stats[key],
                map = branchMap[key],
                covered,
                skipped,
                i;
            for (i = 0; i < branches.length; i += 1) {
                covered = branches[i] > 0;
                skipped = map.locations && map.locations[i] && map.locations[i].skip;
                if (covered || skipped) {
                    ret.covered += 1;
                }
                if (!covered && skipped) {
                    ret.skipped += 1;
                }
            }
            ret.total += branches.length;
        });
        ret.pct = percent(ret.covered, ret.total);
        return ret;
    }
    /**
     * returns a blank summary metrics object. A metrics object has the following
     * format.
     *
     *      {
     *          lines: lineMetrics,
     *          statements: statementMetrics,
     *          functions: functionMetrics,
     *          branches: branchMetrics
     *          linesCovered: lineCoveredCount
     *      }
     *
     *  Each individual metric object looks as follows:
     *
     *      {
     *          total: n,
     *          covered: m,
     *          pct: percent
     *      }
     *
     * @method blankSummary
     * @static
     * @return {Object} a blank metrics object
     */
    function blankSummary() {
        return {
            lines: {
                total: 0,
                covered: 0,
                skipped: 0,
                pct: 'Unknown'
            },
            statements: {
                total: 0,
                covered: 0,
                skipped: 0,
                pct: 'Unknown'
            },
            functions: {
                total: 0,
                covered: 0,
                skipped: 0,
                pct: 'Unknown'
            },
            branches: {
                total: 0,
                covered: 0,
                skipped: 0,
                pct: 'Unknown'
            },
            linesCovered: {}
        };
    }
    /**
     * returns the summary metrics given the coverage object for a single file. See `blankSummary()`
     * to understand the format of the returned object.
     *
     * @method summarizeFileCoverage
     * @static
     * @param {Object} fileCoverage the coverage object for a single file.
     * @return {Object} the summary metrics for the file
     */
    function summarizeFileCoverage(fileCoverage) {
        var ret = blankSummary();
        addDerivedInfoForFile(fileCoverage);
        ret.lines = computeSimpleTotals(fileCoverage, 'l');
        ret.functions = computeSimpleTotals(fileCoverage, 'f', 'fnMap');
        ret.statements = computeSimpleTotals(fileCoverage, 's', 'statementMap');
        ret.branches = computeBranchTotals(fileCoverage);
        ret.linesCovered = fileCoverage.l;
        return ret;
    }
    /**
     * merges two instances of file coverage objects *for the same file*
     * such that the execution counts are correct.
     *
     * @method mergeFileCoverage
     * @static
     * @param {Object} first the first file coverage object for a given file
     * @param {Object} second the second file coverage object for the same file
     * @return {Object} an object that is a result of merging the two. Note that
     *      the input objects are not changed in any way.
     */
    function mergeFileCoverage(first, second) {
        var ret = JSON.parse(JSON.stringify(first)),
            i;

        delete ret.l; //remove derived info

        Object.keys(second.s).forEach(function (k) {
            ret.s[k] += second.s[k];
        });
        Object.keys(second.f).forEach(function (k) {
            ret.f[k] += second.f[k];
        });
        Object.keys(second.b).forEach(function (k) {
            var retArray = ret.b[k],
                secondArray = second.b[k];
            for (i = 0; i < retArray.length; i += 1) {
                retArray[i] += secondArray[i];
            }
        });

        return ret;
    }
    /**
     * merges multiple summary metrics objects by summing up the `totals` and
     * `covered` fields and recomputing the percentages. This function is generic
     * and can accept any number of arguments.
     *
     * @method mergeSummaryObjects
     * @static
     * @param {Object} summary... multiple summary metrics objects
     * @return {Object} the merged summary metrics
     */
    function mergeSummaryObjects() {
        var ret = blankSummary(),
            args = Array.prototype.slice.call(arguments),
            keys = ['lines', 'statements', 'branches', 'functions'],
            increment = function (obj) {
                if (obj) {
                    keys.forEach(function (key) {
                        ret[key].total += obj[key].total;
                        ret[key].covered += obj[key].covered;
                        ret[key].skipped += obj[key].skipped;
                    });

                    // keep track of all lines we have coverage for.
                    Object.keys(obj.linesCovered).forEach(function (key) {
                        if (!ret.linesCovered[key]) {
                            ret.linesCovered[key] = obj.linesCovered[key];
                        } else {
                            ret.linesCovered[key] += obj.linesCovered[key];
                        }
                    });
                }
            };
        args.forEach(function (arg) {
            increment(arg);
        });
        keys.forEach(function (key) {
            ret[key].pct = percent(ret[key].covered, ret[key].total);
        });

        return ret;
    }
    /**
     * returns the coverage summary for a single coverage object. This is
     * wrapper over `summarizeFileCoverage` and `mergeSummaryObjects` for
     * the common case of a single coverage object
     * @method summarizeCoverage
     * @static
     * @param {Object} coverage  the coverage object
     * @return {Object} summary coverage metrics across all files in the coverage object
     */
    function summarizeCoverage(coverage) {
        var fileSummary = [];
        Object.keys(coverage).forEach(function (key) {
            fileSummary.push(summarizeFileCoverage(coverage[key]));
        });
        return mergeSummaryObjects.apply(null, fileSummary);
    }

    /**
     * makes the coverage object generated by this library yuitest_coverage compatible.
     * Note that this transformation is lossy since the returned object will not have
     * statement and branch coverage.
     *
     * @method toYUICoverage
     * @static
     * @param {Object} coverage The `istanbul` coverage object
     * @return {Object} a coverage object in `yuitest_coverage` format.
     */
    function toYUICoverage(coverage) {
        var ret = {};

        addDerivedInfo(coverage);

        Object.keys(coverage).forEach(function (k) {
            var fileCoverage = coverage[k],
                lines = fileCoverage.l,
                functions = fileCoverage.f,
                fnMap = fileCoverage.fnMap,
                o;

            o = ret[k] = {
                lines: {},
                calledLines: 0,
                coveredLines: 0,
                functions: {},
                calledFunctions: 0,
                coveredFunctions: 0
            };
            Object.keys(lines).forEach(function (k) {
                o.lines[k] = lines[k];
                o.coveredLines += 1;
                if (lines[k] > 0) {
                    o.calledLines += 1;
                }
            });
            Object.keys(functions).forEach(function (k) {
                var name = fnMap[k].name + ':' + fnMap[k].line;
                o.functions[name] = functions[k];
                o.coveredFunctions += 1;
                if (functions[k] > 0) {
                    o.calledFunctions += 1;
                }
            });
        });
        return ret;
    }

    /**
     * Creates new file coverage object with incremented hits count
     * on skipped statements, branches and functions
     *
     * @method incrementIgnoredTotals
     * @static
     * @param {Object} cov File coverage object
     * @return {Object} New file coverage object
     */
    function incrementIgnoredTotals(cov) {
        //TODO: This may be slow in the browser and may break in older browsers
        //      Look into using a library that works in Node and the browser
        var fileCoverage = JSON.parse(JSON.stringify(cov));

        [
            {mapKey: 'statementMap', hitsKey: 's'},
            {mapKey: 'branchMap', hitsKey: 'b'},
            {mapKey: 'fnMap', hitsKey: 'f'}
        ].forEach(function (keys) {
            Object.keys(fileCoverage[keys.mapKey])
                .forEach(function (key) {
                    var map = fileCoverage[keys.mapKey][key];
                    var hits = fileCoverage[keys.hitsKey];

                    if (keys.mapKey === 'branchMap') {
                        var locations = map.locations;

                        locations.forEach(function (location, index) {
                            if (hits[key][index] === 0 && location.skip) {
                                hits[key][index] = 1;
                            }
                        });

                        return;
                    }

                    if (hits[key] === 0 && map.skip) {
                        hits[key] = 1;
                    }
                });
            });

        return fileCoverage;
    }

    var exportables = {
        addDerivedInfo: addDerivedInfo,
        addDerivedInfoForFile: addDerivedInfoForFile,
        removeDerivedInfo: removeDerivedInfo,
        blankSummary: blankSummary,
        summarizeFileCoverage: summarizeFileCoverage,
        summarizeCoverage: summarizeCoverage,
        mergeFileCoverage: mergeFileCoverage,
        mergeSummaryObjects: mergeSummaryObjects,
        toYUICoverage: toYUICoverage,
        incrementIgnoredTotals: incrementIgnoredTotals
    };

    /* istanbul ignore else: windows */
    if (isNode) {
        module.exports = exportables;
    } else {
        window.coverageUtils = exportables;
    }
}(typeof module !== 'undefined' && typeof module.exports !== 'undefined' && typeof exports !== 'undefined'));
