"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var objectUtils = require("../utils/object");
var patternUtils = require("../utils/pattern");
/**
 * Returns grouped patterns by base directory of each pattern.
 */
function groupPatternsByParentDirectory(patterns) {
    return patterns.reduce(function (collection, pattern) {
        var parent = patternUtils.getBaseDirectory(pattern);
        if (!collection[parent]) {
            collection[parent] = [];
        }
        collection[parent].push(pattern);
        return collection;
    }, {});
}
exports.groupPatternsByParentDirectory = groupPatternsByParentDirectory;
/**
 * Convert positive patterns to tasks.
 */
function makePositiveTaskGroup(positive) {
    return Object.keys(positive).reduce(function (collection, base) {
        var positivePatterns = [].concat(positive[base]);
        collection[base] = {
            base: base,
            patterns: positivePatterns,
            positive: positivePatterns,
            negative: []
        };
        return collection;
    }, {});
}
exports.makePositiveTaskGroup = makePositiveTaskGroup;
/**
 * Convert negative patterns to tasks.
 */
function makeNegativeTaskGroup(negative) {
    return Object.keys(negative).reduce(function (collection, base) {
        var negativePatterns = [].concat(negative[base]);
        collection[base] = {
            base: base,
            patterns: negativePatterns.map(patternUtils.convertToNegativePattern),
            positive: [],
            negative: negativePatterns
        };
        return collection;
    }, {});
}
exports.makeNegativeTaskGroup = makeNegativeTaskGroup;
/**
 * Returns merged positive and negative task groups.
 *
 * Just two rules:
 *   - If a positive task group has a pair in the negative group, then merge it.
 *   - If a negative task group has a global base task, then merge them to full positive group.
 */
function mergeTaskGroups(positive, negative) {
    var group = positive;
    var globalNegativePatterns = '.' in negative ? negative['.'].negative : [];
    Object.keys(group).forEach(function (base) {
        if (base in negative) {
            group[base].patterns = group[base].patterns.concat(negative[base].negative.map(patternUtils.convertToNegativePattern));
            group[base].negative = group[base].negative.concat(negative[base].negative);
        }
        if (globalNegativePatterns.length !== 0) {
            group[base].patterns = group[base].patterns.concat(globalNegativePatterns.map(patternUtils.convertToNegativePattern));
            group[base].negative = group[base].negative.concat(globalNegativePatterns);
        }
    });
    return group;
}
exports.mergeTaskGroups = mergeTaskGroups;
/**
 * Returns builded tasks for provided patterns groups.
 */
function makeTasks(positive, negative) {
    var positiveTaskGroup = makePositiveTaskGroup(positive);
    var negativeTaskGroup = makeNegativeTaskGroup(negative);
    var groups = mergeTaskGroups(positiveTaskGroup, negativeTaskGroup);
    return objectUtils.values(groups);
}
exports.makeTasks = makeTasks;
/**
 * Generate tasks for provided patterns based on base directory of each pattern.
 */
function generate(patterns, options) {
    var unixPatterns = patterns.map(patternUtils.unixifyPattern);
    var positive = patternUtils.getPositivePatterns(unixPatterns);
    if (positive.length === 0) {
        return [];
    }
    var ignore = options.ignore;
    var negative = patternUtils.getNegativePatterns(unixPatterns)
        .map(patternUtils.convertToPositivePattern)
        .concat(ignore)
        .map(patternUtils.trimTrailingSlashGlobStar);
    var positiveGroup = groupPatternsByParentDirectory(positive);
    var negativeGroup = groupPatternsByParentDirectory(negative);
    // When we have a global group – there is no reason to divide the patterns into independent tasks because the first task covers the rest.
    if ('.' in positiveGroup) {
        var task = {
            base: '.',
            patterns: [].concat(positive, negative.map(patternUtils.convertToNegativePattern)),
            positive: positive,
            negative: negative
        };
        return [task];
    }
    return makeTasks(positiveGroup, negativeGroup);
}
exports.generate = generate;
