'use strict';

const stripJs = require('strip-js');
const globalHooks = require('../../../hooks');
const hooks = require('feathers-hooks');
const auth = require('feathers-authentication');

const getAverageRating = function(submissions){
    // Durchschnittsnote berechnen
    if (submissions.length > 0) {
        // Nur bewertete Abgaben einbeziehen
        let submissiongrades = submissions.filter(s => Number.isInteger(s.grade));
        // Abgaben vorhanden?
        if(submissiongrades.length > 0){
            // Noten aus Abgabe auslesen
            submissiongrades = submissiongrades.map(s => s.grade);
            // Durchschnittsnote berechnen
            const ratingsum = submissiongrades.reduce(function(a, b) { return a + b; }, 0);
            return (ratingsum / submissiongrades.length).toFixed(2);
        }
    }
    return undefined;
};

const filterApplicableHomework = hook => {
    let data = hook.result.data || hook.result;
    data = data.filter(function (c) {
        return (new Date(c.availableDate).getTime() < Date.now()
            && c.courseId != null
            && ((c.courseId.userIds || []).indexOf(hook.params.account.userId) != -1) && !c.private)
          || JSON.stringify(c.teacherId) == JSON.stringify(hook.params.account.userId);
    });
    return Promise.resolve(hook);
};

const hasViewPermission = hook => {
    if(!hook.params.query['$populate'].includes('courseId')){
        hook.params.query['$populate'].push('courseId');
    }

    if(!hook.params.query['$or']){
        hook.params.query['$or'] = [
            {teacherId: hook.params.account.userId},
            {
                'courseId.userIds': hook.params.account.userId,
                'private': false,
                'availableDate': { $lte: Date.now() }
            }
        ];
    }else{
        hook.params.query['$or'].push({teacherId: hook.params.account.userId});
        hook.params.query['$or'].push({ 'courseId.userIds': hook.params.account.userId,
                                        'private': false,
                                        'availableDate': { $lte: Date.now() } });
    }
    return Promise.resolve(hook);
}

const addStats = hook => {
    let data = hook.result.data || hook.result;
    const submissionService = hook.app.service('/submissions');
    const arrayed = !(Array.isArray(data));
    data = (Array.isArray(data))?(data):([data]);
    return submissionService.find({query: {
            homeworkId: {$in: (data.map(n => n._id))}
        }}).then((submissions) => {
            data = data.map(function(e){
                var c = JSON.parse(JSON.stringify(e)) // don't know why, but without this line it's not working :/
                if(!c.private){
                    let submissionP = (submissions.data.filter(function(n){return JSON.stringify(c._id) == JSON.stringify(n.homeworkId)
                        && n.comment != undefined && n.comment != ""}).length/((c.courseId || {}).userIds || []).length)*100;
                    let gradeP = (submissions.data.filter(function(n){return JSON.stringify(c._id) == JSON.stringify(n.homeworkId)
                            && ( n.gradeComment != '' || Number.isInteger(n.grade) )}).length/((c.courseId || {}).userIds || []).length)*100;
                    c.stats = {
                        userCount: ((c.courseId || {}).userIds || []).length,
                        submissionCount: submissions.data.filter(function(n){return JSON.stringify(c._id) == JSON.stringify(n.homeworkId)
                            && n.comment != undefined && n.comment != ""}).length,
                        submissionPercentage: (submissionP && submissionP != Infinity)?submissionP.toFixed(2):undefined,
                        gradeCount: submissions.data.filter(function(n){return JSON.stringify(c._id) == JSON.stringify(n.homeworkId)
                            && ( n.gradeComment != '' || Number.isInteger(n.grade) )}).length,
                        gradePercentage: (gradeP && gradeP != Infinity)?gradeP.toFixed(2):undefined,
                        averageGrade: getAverageRating(submissions.data.filter(function(n){return JSON.stringify(c._id) == JSON.stringify(n.homeworkId);}))
                    };
                }
                return c;
            });
            if(arrayed){data = data[0];}
            (hook.result.data)?(hook.result.data = data):(hook.result = data);
    });
}

exports.before = {
    all: [auth.hooks.authenticate('jwt'), (hook) => {
        if (hook.data && hook.data.description) {
            hook.data.description = stripJs(hook.data.description);
        }

        return hook;
    }],
    find: [globalHooks.mapPaginationQuery.bind(this), hasViewPermission],
    get: [hasViewPermission],
    create: [],
    update: [],
    patch: [],
    remove: []
};

exports.after = {
  all: [],
  find: [addStats],
  get: [addStats],
  create: [],
  update: [],
  patch: [],
  remove: []
};

@@ -863,281 +863,89 @@
 nst 
-filterApplicableHomework = hook =%3E %7B%0A    let data = hook.result.data %7C%7C hook.result;%0A    data = data.filter(function (c) %7B%0A        return (new Date(c.availableDate).getTime() %3C Date.now()%0A            && c.courseId != null%0A            && ((c.courseId.userIds %7C%7C %5B%5D).indexO
+hasViewPermission = hook =%3E %7B%0A    if(hook.params.query%5B'$populate'%5D)%0A        i
 f(
+!
 hook
@@ -956,224 +956,63 @@
 ams.
-account.userId) != -1) && !c.private)%0A          %7C%7C JSON.stringify(c.teacherId) == JSON.stringify(hook.params.account.u
+query%5B'$populate'%5D.includes('cour
 se
-r
 Id
-);%0A    %7D);%0A    return Promise.resolve(hook);%0A%7D;%0A%0Aconst hasViewPermission = hook =%3E %7B%0A    if(!
+')))%7B%0A            
 hook
@@ -1034,32 +1034,28 @@
 $populate'%5D.
-includes
+push
 ('courseId')
@@ -1054,17 +1054,37 @@
 urseId')
-)
+;%0A        %7D%0A    %7Delse
 %7B%0A      
@@ -1107,38 +1107,36 @@
 ery%5B'$populate'%5D
-.push(
+ = %5B
 'courseId');%0A   
@@ -1125,25 +1125,25 @@
  %5B'courseId'
-)
+%5D
 ;%0A    %7D%0A%0A   

make code more robust