'use strict';
const Router = require('koa-router');
const logger = require('logger');
const ErrorSerializer = require('serializers/errorSerializer');
const QuestionnaireSerializer = require('serializers/questionnaireSerializer');
const QuestionnaireModel = require('models/questionnaireModel');
const QuestionnaireValidator = require('validators/questionnaireValidator');
const AnswerModel = require('models/answerModel');
const passThrough = require('stream').PassThrough;
const json2csv = require('json2csv');

const router = new Router({
    prefix: '/questionnaire',
});

class QuestionnaireRouter {

    static * getAll(){
        logger.info('Obtaining all questionnaires');
        const questionnaireModels = yield QuestionnaireModel.find();
        this.body = QuestionnaireSerializer.serialize(questionnaireModels);
    }

    static * get(){
        logger.info(`Obtaining questionnaire with id ${this.params.id}`);
        const questionnaire = yield QuestionnaireModel.find({ _id: this.params.id });
        this.body = QuestionnaireSerializer.serialize(questionnaire);
    }

    static * save(){
        logger.info('Saving questionnaire');
        const questionnaire = yield new QuestionnaireModel({
            name: this.request.body.name,
            questions: this.request.body.questions
        }).save();
        this.body = QuestionnaireSerializer.serialize(questionnaire);
    }

    static * update(){
        this.throw(500, 'Not implemented');
        return;
    }

    static * delete(){
        logger.info(`Deleting questionnaire with id ${this.params.id}`);
        const result = yield QuestionnaireModel.remove({ _id: this.params.id });
        if (!result || !result.result || result.result.ok === 0) {
            this.throw(404, 'Questionnaire not found');
            return;
        }
        this.body = '';
        this.statusCode = 204;
    }

    static * downloadAnswers() {
        logger.info(`Download answers of questionnaire ${this.params.id}`);
        this.set('Content-disposition', `attachment; filename=${this.params.id}.csv`);
        this.set('Content-type', 'text/csv');
        this.body = passThrough();

        const questionnaire = yield QuestionnaireModel.findById(this.params.id);
        const questions = {};
        if (!questionnaire) {
            ctx.throw(404, 'Not found');
            return;
        }
        for (let i = 0, length = questionnaire.questions.length; i < length; i++) {
            const question = questionnaire.questions[i]
            questions[question.name] = null;
            if (question.childQuestions){
                for (let j = 0, lengthChild =question.childQuestions.length; j < lengthChild; j++ ){
                    questions[question.childQuestions[j].name] = null;
                }
            }
        } 
        const answers = yield AnswerModel.find({
            questionnaire: this.params.id
        });
        logger.debug('Obtaining data');
        if (answers) {
            logger.debug('Data found!');
            let data = null;
            
            for (let i = 0, length = answers.length; i < length; i++) {
                const answer = answers[i];
                const responses = Object.assign({}, questions);
                answer.responses.map((res) => {
                    responses[res.question] = res.value;
                });
                logger.debug('Writting...');
                data = json2csv({
                    data: responses,
                    hasCSVColumnTitle: i === 0
                }) + '\n';
                this.body.write(data);
            }
        }
        this.body.end();    
    }

}


function * loggedUserToState(next) {
    if (this.query && this.query.loggedUser){
        this.state.loggedUser = JSON.parse(this.query.loggedUser);
        delete this.query.loggedUser;
    } else if (this.request.body && this.request.body.loggedUser) {
        this.state.loggedUser = this.request.body.loggedUser;
        delete this.request.body.loggedUser;
    } else {
        this.throw(401, 'Not logged');
        return;
    }
    yield next;
}

function * checkPermission(next) {
    if (this.state.loggedUser.role === 'USER' || (this.state.loggedUser.role==='MANAGER' && (!this.state.loggedUser.extraUserData || this.state.loggedUser.extraUserData.apps || this.state.loggedUser.extraUserData.apps.indexOf('gfw') === -1))) {
        this.throw(403, 'Not authorized');
        return;
    }
    yield next;
}

function* checkAdmin(next) {
    if (!this.state.loggedUser || this.state.loggedUser.role !== 'ADMIN') {
        this.throw(403, 'Not authorized');
        return;
    }
    yield next;
}

router.post('/', loggedUserToState, QuestionnaireValidator.create, QuestionnaireRouter.save);
router.patch('/:id', loggedUserToState, checkPermission, QuestionnaireValidator.update, QuestionnaireRouter.update);
router.get('/', loggedUserToState, QuestionnaireRouter.getAll);
router.get('/:id', loggedUserToState, QuestionnaireRouter.get);
router.delete('/:id', loggedUserToState, checkPermission, QuestionnaireRouter.delete);
router.get('/:id/download-answers', loggedUserToState, checkAdmin, QuestionnaireRouter.downloadAnswers);

module.exports = router;

@@ -2316,11 +2316,12 @@
     
-ctx
+this
 .thr
@@ -2511,16 +2511,17 @@
 tions%5Bi%5D
+;
 %0A       
@@ -3263,39 +3263,145 @@
     
-answer.responses.map((res) =%3E %7B
+for(let j = 0, lengthResponses = answer.responses.length; j %3C lengthResponses; j++)%7B%0A                    const res = answer.responses%5Bj%5D;
 %0A   
@@ -3454,16 +3454,16 @@
 .value;%0A
+
         
@@ -3463,34 +3463,32 @@
                %7D
-);
 %0A               

improve code