var _ = require('lodash');

var ressourcesMap = require('./ressources');

var ind = require('./individu');
var men = require('./menage');
var fam = require('./famille');
var foy = require('./foyerFiscal');

var isNotValidValue = function(value) {
    return _.isNaN(value) || _.isUndefined(value) || value === null;
};

var applyRessources = function(src, dest, schema) {
    var ressourcesByType = _.groupBy(src.ressources, 'type');
    _.forEach(schema, function(definition, destKey) {
        var srcKey, fn;
        if (_.isString(definition)) {
            srcKey = definition;
        } else {
            srcKey = definition.src;
            fn = definition.fn;
        }

        if (ressourcesByType[srcKey]) {
            var result = {};
            _.forEach(ressourcesByType[srcKey], function(item) {
                if (item.periode) {
                    if (!result[item.periode]) result[item.periode] = 0;
                    result[item.periode] += item.montant;
                }
            });

            _.forEach(result, function(montant, periode) {
                // Applique la transformation
                if (fn) montant = fn(montant);

                result[periode] = montant;
            });

            if (_.size(result) > 0) dest[destKey] = result;
        }
    });
};

var transform = function(src, schema, situation) {
    var result = {};
    _.forEach(schema, function(definition, destKey) {
        var params = _.isString(definition) ? { src: definition } : definition;

        if (params.values) {
            result[destKey] = params.values[src[params.src]];
        } else if (params.fn) {
            result[destKey] = params.src ? params.fn(src[params.src], src, situation) : params.fn(src, situation);
        } else {
            result[destKey] = src[params.src];
        }

        if (params.round && _.isNumber(result[destKey])) {
            result[destKey] = Math.round(result[destKey]);
        }

        // Supprime les null (mal supportés par OpenFisca)
        if (isNotValidValue(result[destKey])) {
            if ('default' in params) result[destKey] = params.default;
            else delete result[destKey];
        }
    });
    return result;
};

var mapIndividus = function(situation) {
    return _.map(situation.individus, function(individu) {
        if (individu.role === 'demandeur') {
            _.extend(individu, situation.patrimoine);

            var revenusLocatifs = situation.patrimoine.revenusLocatifs.map(function(revenu) {
                revenu.type = 'revenusLocatifs';
                return revenu;
            });

            var revenusDuCapital = situation.patrimoine.revenusDuCapital.map(function(revenu) {
                revenu.type = 'revenusDuCapital';
                return revenu;
            });

            individu.ressources = individu.ressources.concat(revenusLocatifs, revenusDuCapital);
        }
        var target = transform(individu, ind, situation);
        applyRessources(individu, target, ressourcesMap.individu);
        return target;
    });
};

var mapFamille = function(situation) {
    var famille = transform(situation, fam, situation);
    var ressources = [];
    _.forEach(situation.individus, function(individu) { ressources = ressources.concat(individu.ressources); });
    applyRessources({ ressources: ressources }, famille, ressourcesMap.famille);

    return famille;
};

exports.mapSituation = function(situation) {
    return {
        familles: [mapFamille(situation)],
        foyers_fiscaux: [transform(situation, foy, situation)],
        individus: mapIndividus(situation),
        menages: [transform(situation.logement, men, situation)]
    };
};

@@ -19,16 +19,48 @@
 odash');
+%0Avar moment = require('moment');
 %0A%0Avar re
@@ -393,19 +393,301 @@
 , schema
-) %7B
+, dateDeValeur) %7B%0A    var debutAnneeGlissante = moment(dateDeValeur, 'YYYY-MM-DD').subtract(1, 'years').subtract(1, 'months');%0A    var finAnneeGlissante = moment(dateDeValeur, 'YYYY-MM-DD');%0A    var anneeFiscaleNMoins2 = moment(dateDeValeur, 'YYYY-MM-DD').subtract(2, 'years').year();%0A
 %0A    var
@@ -1052,24 +1052,64 @@
 esult = %7B%7D;%0A
+            var surAnneeGlissante = 0;%0A%0A
             
@@ -1319,32 +1319,303 @@
 += item.montant;
+%0A%0A                    var periode = moment(item.periode, 'YYYY-MM');%0A%0A                    if (periode.isAfter(debutAnneeGlissante, 'month') && periode.isBefore(finAnneeGlissante, 'month')) %7B%0A                        surAnneeGlissante += item.montant;%0A                    %7D
 %0A               
@@ -1867,50 +1867,220 @@
 if (
-_.size(result) %3E 0) dest%5BdestKey%5D = result
+fn) surAnneeGlissante = fn(surAnneeGlissante);%0A%0A            if (_.size(result) %3E 0) dest%5BdestKey%5D = result;%0A            if (surAnneeGlissante %3E 0) dest%5BdestKey%5D%5BanneeFiscaleNMoins2.toString()%5D = surAnneeGlissante
 ;%0A  
@@ -3822,16 +3822,40 @@
 individu
+, situation.dateDeValeur
 );%0A     
@@ -4195,16 +4195,40 @@
 .famille
+, situation.dateDeValeur
 );%0A%0A    

Copie année glissante dans année fiscale N-2