/**
 * @file Resolvers pour tous les types de messages
 * @author akka, ofacklam
 */

import {Group, SimpleGroup, MetaGroup} from './groups';
import {User} from './users';
import knex from '../../../db/knex_router';
import { Context } from '../typeDefs/queries';
import { ApolloError } from 'apollo-server-core';
import { GroupSet } from '../models/tools';

export abstract class Message {

    /**
     * @memberof GraphQL
     * @class Message
     * @summary Resolvers des messages
     * @classdesc Une classe abstraite représentant l'interface Message du schéma.
     * Comme Apollo Server, par défaut, appelle la propriété / fonction avec le nom a résoudre, il n'y a pas besoin d'écrire les resolvers explicitement.
     * @arg {number} mid - Identifiant du message, supposé valide.
     * @rights dépend du type de message
     * @abstract
     */
    constructor(mid: number) {
        this.mid = mid;
        this.m_dataLoaded = false;
    }

    /**
     * @memberof GraphQL.Message#
     * @function fetchData
     * @summary Fonction qui va chercher toutes les données sur ce message dans la BDD, si ce n'est pas déja fait.
     * @returns {Promise(boolean)} Renvoie true si le chargement est réussi.
     * @async
     * @protected
     * @abstract
     */
    protected abstract async fetchData(): Promise<boolean>

    /**
     * Protected properties.
     * Ce sont tous les champs triviaux, ie qui peuvent etre récupérés en une seule requete a la BDD,
     * ce qui permet d'etre plus efficace.
     * La variable dataLoaded témoigne de si on est déja allés chercher les données.
     * ATTENTION. Ce ne sont PAS directement les resolvers, il FAUT donc qu'ils aient un nom DIFFÉRENT du nom des champs dans le schéma.
     */
    protected m_dataLoaded: boolean
    
    protected m_createdAt: string
    protected m_updatedAt: string
    protected m_title: string
    protected m_content: string

    /**
     * Ci-dessous les resolvers a proprement parler.
     */

    /**
     * @memberof GraphQL.Message#
     * @function __resolveType
     * @summary Renvoie quel type de Message c'est
     * @return {string}
     * @rights same as message object
     */
    __resolveType(): string {
        if (this instanceof Announcement) {
            return "Announcement";
        }
        else if (this instanceof Event) {
            return "Event";
        }
        else if (this instanceof Question) {
            return "Question";
        }
        else if (this instanceof Answer) {
            return "Answer";
        }
        else if (this instanceof PrivatePost) {
            return "PrivatePost";
        }
        else {
            throw new ApolloError("Bad message type");
        }
    }

    /** @rights same as message object */
    mid: number;

    /**
     * @memberof GraphQL.Message#
     * @function createdAt
     * @summary Renvoie la date de création
     * @return {Promise(string)}
     * @rights same as message object
     * @async
     */
    async createdAt(args, context: Context, info): Promise<string> {
        await this.fetchData();
        return this.m_createdAt;
    }

    /**
     * @memberof GraphQL.Message#
     * @function updatedAt
     * @summary Renvoie la date de mise a jour
     * @return {Promise(string)}
     * @rights same as message object
     * @async
     */
    async updatedAt(args, context: Context, info): Promise<string> {
        await this.fetchData();
        return this.m_updatedAt;
    }

    /**
     * @memberof GraphQL.Message#
     * @function title
     * @summary Renvoie le titre du message
     * @return {Promise(string)}
     * @rights same as message object
     * @async
     */
    async title(args, context: Context, info): Promise<string> {
        await this.fetchData();
        return this.m_title;
    }

    /**
     * @memberof GraphQL.Message#
     * @function content
     * @summary Renvoie le contenu du message
     * @return {Promise(string)}
     * @rights same as message object
     * @async
     */
    async content(args, context: Context, info): Promise<string> {
        await this.fetchData();
        return this.m_content;
    }
}

export class Announcement extends Message {

    /**
     * @memberof GraphQL
     * @class Announcement
     * @extends GraphQL.Message
     * @summary Resolvers des announcements
     * @classdesc Une classe représentant le type Announcement du schéma.
     * Comme Apollo Server, par défaut, appelle la propriété / fonction avec le nom a résoudre, il n'y a pas besoin d'écrire les resolvers explicitement.
     * @arg {number} mid - Identifiant du message, supposé valide.
     * @rights membre d'un groupe author ou d'un groupe recipient
     */
    constructor(mid: number) {
        super(mid);
        this.m_authors = new GroupSet();
        this.m_recipients = new GroupSet();
    }

    /**
     * @memberof GraphQL.Announcement#
     * @function tryCreate
     * @summary Fonction qui va essayer de créer l'annonce correspondante
     * @arg {number} mid - Identifiant du message, sans hypothese sur la validité.
     * @returns {Promise(Announcement)} - Renvoie le Announcement créé, ou null en cas d'erreur.
     * @rights membre d'un groupe author ou d'un groupe recipient
     * @async
     * @static
     */
    static async tryCreate(mid: number): Promise<Announcement> {
        let m = new Announcement(mid);
        if(await m.fetchData()) {
            return m;
        }
        return null;
    }

    /**
     * @memberof GraphQL.Announcement#
     * @function fetchData
     * @summary Fonction qui va chercher toutes les données sur cet announcement dans la BDD, si ce n'est pas déja fait.
     * @returns {Promise(boolean)} Renvoie true si le chargement est réussi.
     * @async
     * @protected
     */
    protected async fetchData(): Promise<boolean> {
        if(!this.m_dataLoaded) {
            let data = await knex.select('created_at',
                'updated_at',
                'title',
                'content',
                //'importance', 
                'views').from('messages_announcements').where('mid', this.mid);

            if (data.length > 0) {
                let m = data[0];

                this.m_createdAt = m.created_at;
                this.m_updatedAt = m.updated_at;
                this.m_title = m.title;
                this.m_content = m.content;
                //this.m_importance = m.importance;
                this.m_views = m.views;

                this.m_dataLoaded = true;
            }
            else {
                return false;
            }

            //Charge les authors dans m_authors

            data = await knex.select('gid').from('announcements_authors').where('mid', this.mid);

            for(let t of data) {
                this.m_authors.add(t.gid);
            }

            //Charge les recipients dans m_recipients
            
            data = await knex.select('gid').from('announcements_recipients').where('mid', this.mid);

            for (let t of data) {
                this.m_authors.add(t.gid);
            }
        }

        return true;
    }

    /**
     * Protected properties.
     * Ce sont tous les champs triviaux, ie qui peuvent etre récupérés en une seule requete a la BDD,
     * ce qui permet d'etre plus efficace.
     * La variable dataLoaded témoigne de si on est déja allés chercher les données.
     * ATTENTION. Ce ne sont PAS directement les resolvers, il FAUT donc qu'ils aient un nom DIFFÉRENT du nom des champs dans le schéma.
     */
    protected m_importance: number
    protected m_views : number
    protected m_authors : GroupSet
    protected m_recipients : GroupSet

    /**
     * Ci-dessous les resolvers a proprement parler.
     */

    /**
     * @memberof GraphQL.Announcement#
     * @function authors
     * @summary Renvoie les groupes auteurs
     * @return {Promise(Group[])}
     * @rights membre d'un groupe author ou d'un groupe recipient
     * @async
     */
    async authors(args, context: Context, info): Promise<Group[]> {
        //TODO: verifier les authorisations
        throw "Not implemented";

        await this.fetchData();
        var ret:Group[];
        for(let t of this.m_authors) {
            ret.push(new SimpleGroup(t));
        }
        return ret;
    }

    /**
     * @memberof GraphQL.Announcement#
     * @function recipients
     * @summary Renvoie les groupes destinataires
     * @return {Promise(Group[])}
     * @rights membre d'un groupe author ou d'un groupe recipient
     * @async
     */
    async recipients(args, context: Context, info): Promise<Group[]> {
        //TODO: verifier les authorisations
        throw "Not implemented";

        await this.fetchData();
        var ret: Group[];
        for (let t of this.m_recipients) {
            ret.push(new SimpleGroup(t));
        }
        return ret;
    }

    /**
     * @memberof GraphQL.Announcement#
     * @function importance
     * @summary Renvoie l'importance
     * @return {Promise(number)}
     * @rights membre d'un groupe author ou d'un groupe recipient
     * @async
     */
    async importance(args, context: Context, info): Promise<number> {
        await this.fetchData();
        return this.m_importance;
    }

    /**
     * @memberof GraphQL.Announcement#
     * @function views
     * @summary Renvoie le nombre de vues
     * @return {Promise(number)}
     * @rights membre d'un groupe author ou d'un groupe recipient
     * @async
     */
    async views(args, context: Context, info): Promise<number> {
        await this.fetchData();
        return this.m_views;
    }

    /**
     * @memberof GraphQL.Announcement#
     * @function forEvent
     * @summary Renvoie l'evenement correspondant, s'il existe
     * @return {Promise(Event)}
     * @rights membre d'un groupe author ou d'un groupe recipient
     * @async
     */
    async forEvent(args, context: Context, info): Promise<Event> {
        let data = await knex.select('mid').from('messages_events').where('for_announcement', this.mid);
        if(data.length > 0) {
            return new Event(data[0].mid);
        }
        return null;
    }
}

export class Event extends Message {

    /**
     * @memberof GraphQL
     * @class Event
     * @extends GraphQL.Message
     * @summary Resolvers des events
     * @classdesc Une classe représentant le type Event du schéma.
     * Comme Apollo Server, par défaut, appelle la propriété / fonction avec le nom a résoudre, il n'y a pas besoin d'écrire les resolvers explicitement.
     * @arg {number} mid - Identifiant du message, supposé valide.
     * @rights membre d'un groupe author ou d'un groupe recipient
     */
    constructor(mid: number) {
        super(mid);
    }

    /**
     * @memberof GraphQL.Event#
     * @function tryCreate
     * @summary Fonction qui va essayer de créer l'evenement correspondant
     * @arg {number} mid - Identifiant du message, sans hypothese sur la validité.
     * @returns {Promise(Event)} - Renvoie le Event créé, ou null en cas d'erreur.
     * @rights membre d'un groupe author ou d'un groupe recipient
     * @async
     * @static
     */
    static async tryCreate(mid: number): Promise<Event> {
        let m = new Event(mid);
        if(await m.fetchData()) {
            return m;
        }
        return null;
    }

    /**
     * @memberof GraphQL.Event#
     * @function fetchData
     * @summary Fonction qui va chercher toutes les données sur cet event dans la BDD, si ce n'est pas déja fait.
     * @returns {Promise(boolean)} Renvoie true si le chargement est réussi.
     * @async
     * @protected
     */
    protected async fetchData(): Promise<boolean> {
        if (!this.m_dataLoaded) {
            let data = await knex.select('created_at',
                'updated_at',
                'title',
                'content',
                'location', 
                'start_time', 
                'end_time', 
                'for_announcement').from('messages_events').where('mid', this.mid);

            if (data.length > 0) {
                let m = data[0];

                this.m_createdAt = m.created_at;
                this.m_updatedAt = m.updated_at;
                this.m_title = m.title;
                this.m_content = m.content;
                this.m_location = m.location;
                this.m_startTime = m.start_time;
                this.m_endTime = m.end_time;
                this.m_forAnnouncement = m.for_announcement;

                this.m_dataLoaded = true;
                return true;
            }
            else {
                return false;
            }
        }
        return true;
    }

    /**
     * Protected properties.
     * Ce sont tous les champs triviaux, ie qui peuvent etre récupérés en une seule requete a la BDD,
     * ce qui permet d'etre plus efficace.
     * La variable dataLoaded témoigne de si on est déja allés chercher les données.
     * ATTENTION. Ce ne sont PAS directement les resolvers, il FAUT donc qu'ils aient un nom DIFFÉRENT du nom des champs dans le schéma.
     */
    protected m_location: string
    protected m_startTime: string
    protected m_endTime: string
    protected m_forAnnouncement: number

    /**
     * Ci-dessous les resolvers a proprement parler.
     */

    /**
     * @memberof GraphQL.Event#
     * @function authors
     * @summary Renvoie les groupes auteurs
     * @return {Promise(Group[])}
     * @rights membre d'un groupe author ou d'un groupe recipient
     * @async
     */
    async authors(args, context: Context, info): Promise<Group[]> {
        throw "Not implemented";

        /*return knex.select({ uid: 'group' }).from('group_message_relationships')
            .where('message', messageID).whereIn('status', ['host', 'publish']);*/
    }

    /**
     * @memberof GraphQL.Event#
     * @function recipients
     * @summary Renvoie les groupes destinataires
     * @return {Promise(Group[])}
     * @rights membre d'un groupe author ou d'un groupe recipient
     * @async
     */
    async recipients(args, context: Context, info): Promise<Group[]> {
        throw "Not implemented";

        /*return knex.select({ uid: 'group' }).from('group_message_relationships')
            .where('message', messageID).where('status', 'recieve');*/
    }

    /**
     * @memberof GraphQL.Event#
     * @function location
     * @summary Renvoie l'endroit
     * @return {Promise(string)}
     * @rights membre d'un groupe author ou d'un groupe recipient
     * @async
     */
    async location(args, context: Context, info): Promise<string> {
        await this.fetchData();
        return this.m_location;
    }
    
    /**
     * @memberof GraphQL.Event#
     * @function startTime
     * @summary Renvoie l'horaire de début
     * @return {Promise(string)}
     * @rights membre d'un groupe author ou d'un groupe recipient
     * @async
     */
    async startTime(args, context: Context, info): Promise<string> {
        await this.fetchData();
        return this.m_startTime;
    }

    /**
     * @memberof GraphQL.Event#
     * @function endTime
     * @summary Renvoie l'horaire de fin
     * @return {Promise(string)}
     * @rights membre d'un groupe author ou d'un groupe recipient
     * @async
     */
    async endTime(args, context: Context, info): Promise<string> {
        await this.fetchData();
        return this.m_endTime;
    }

    /**
     * @memberof GraphQL.Event#
     * @function participatingGroups
     * @summary Renvoie les groupes qui participent
     * @return {Promise(Group[])}
     * @rights membre d'un groupe author ou d'un groupe recipient
     * @async
     */
    async participatingGroups(args, context: Context, info): Promise<Group[]> {
        throw "Not implemented";
    }

    /**
     * @memberof GraphQL.Event#
     * @function participatingUsers
     * @summary Renvoie les users qui participent
     * @return {Promise(User[])}
     * @rights membre d'un groupe author ou d'un groupe recipient
     * @async
     */
    async participatingUsers(args, context: Context, info): Promise<User[]> {
        throw "Not implemented";
    }

    /**
     * @memberof GraphQL.Event#
     * @function forAnnouncement
     * @summary Renvoie l'announcement correspondant, s'il existe
     * @return {Promise(Announcement)}
     * @rights membre d'un groupe author ou d'un groupe recipient
     * @async
     */
    async forAnnouncement(args, context: Context, info): Promise<Announcement> {
        await this.fetchData();
        if (this.m_forAnnouncement == 0) { //what is the default ?????
            return null;
        } 
        else {
            return new Announcement(this.m_forAnnouncement);
        }
    }
}

export class PrivatePost extends Message {

    /**
     * @memberof GraphQL
     * @class PrivatePost
     * @extends GraphQL.Message
     * @summary Resolvers des posts privés
     * @classdesc Une classe représentant le type PrivatePost du schéma.
     * Comme Apollo Server, par défaut, appelle la propriété / fonction avec le nom a résoudre, il n'y a pas besoin d'écrire les resolvers explicitement.
     * @arg {number} mid - Identifiant du message, supposé valide.
     * @rights membre du groupe recipient
     */
    constructor(mid: number) {
        super(mid);
    }

    /**
     * @memberof GraphQL.PrivatePost#
     * @function tryCreate
     * @summary Fonction qui va essayer de créer le post privé correspondant
     * @arg {number} mid - Identifiant du message, sans hypothese sur la validité.
     * @returns {Promise(PrivatePost)} - Renvoie le PrivatePost créé, ou null en cas d'erreur.
     * @rights membre du groupe recipient
     * @async
     * @static
     */
    static async tryCreate(mid: number): Promise<PrivatePost> {
        let m = new PrivatePost(mid);
        if(await m.fetchData()) {
            return m;
        }
        return null;
    }

    /**
     * @memberof GraphQL.PrivatePost#
     * @function fetchData
     * @summary Fonction qui va chercher toutes les données sur ce post privé dans la BDD, si ce n'est pas déja fait.
     * @returns {Promise(boolean)} Renvoie true si le chargement est réussi.
     * @async
     * @protected
     */
    protected async fetchData(): Promise<boolean> {
        if (!this.m_dataLoaded) {
            let data = await knex.select('created_at',
                'updated_at',
                'title',
                'content',
                'author',
                'recipient').from('messages_private_posts').where('mid', this.mid);

            if (data.length > 0) {
                let m = data[0];

                this.m_createdAt = m.created_at;
                this.m_updatedAt = m.updated_at;
                this.m_title = m.title;
                this.m_content = m.content;
                this.m_author = m.author;
                this.m_recipient = m.recipient;

                this.m_dataLoaded = true;
                return true;
            }
            else {
                return false;
            }
        }
        return true;
    }

    /**
     * Protected properties.
     * Ce sont tous les champs triviaux, ie qui peuvent etre récupérés en une seule requete a la BDD,
     * ce qui permet d'etre plus efficace.
     * La variable dataLoaded témoigne de si on est déja allés chercher les données.
     * ATTENTION. Ce ne sont PAS directement les resolvers, il FAUT donc qu'ils aient un nom DIFFÉRENT du nom des champs dans le schéma.
     */
    protected m_author: string
    protected m_recipient: string

    /**
     * Ci-dessous les resolvers a proprement parler.
     */

    /**
     * @memberof GraphQL.PrivatePost#
     * @function author
     * @summary Renvoie le user auteur
     * @return {Promise(User)}
     * @rights membre du groupe recipient
     * @async
     */
    async author(args, context: Context, info): Promise<User> {
        await this.fetchData();
        return new User(this.m_author);
    }

    /**
     * @memberof GraphQL.PrivatePost#
     * @function recipient
     * @summary Renvoie le groupe destinataire
     * @return {Promise(Group)}
     * @rights membre du groupe recipient
     * @async
     */
    async recipient(args, context: Context, info): Promise<Group> {
        await this.fetchData();
        throw "Not implemented";
    }
}

export class Question extends Message {

    /**
     * @memberof GraphQL
     * @class Question
     * @extends GraphQL.Message
     * @summary Resolvers des questions
     * @classdesc Une classe représentant le type Question du schéma.
     * Comme Apollo Server, par défaut, appelle la propriété / fonction avec le nom a résoudre, il n'y a pas besoin d'écrire les resolvers explicitement.
     * @arg {number} mid - Identifiant du message, supposé valide.
     * @rights viewer du groupe recipient
     */
    constructor(mid: number) {
        super(mid);
    }

    /**
     * @memberof GraphQL.Question#
     * @function tryCreate
     * @summary Fonction qui va essayer de créer la question correspondante
     * @arg {number} mid - Identifiant du message, sans hypothese sur la validité.
     * @returns {Promise(Question)} - Renvoie la Question créée, ou null en cas d'erreur.
     * @rights viewer du groupe recipient
     * @async
     * @static
     */
    static async tryCreate(mid: number): Promise<Question> {
        let m = new Question(mid);
        if(await m.fetchData()) {
            return m;
        }
        return null;
    }

    /**
     * @memberof GraphQL.Question#
     * @function fetchData
     * @summary Fonction qui va chercher toutes les données sur ce post privé dans la BDD, si ce n'est pas déja fait.
     * @returns {Promise(boolean)} Renvoie true si le chargement est réussi.
     * @async
     * @protected
     */
    protected async fetchData(): Promise<boolean> {
        if (!this.m_dataLoaded) {
            let data = await knex.select('created_at',
                'updated_at',
                'title',
                'content',
                'author',
                'recipient').from('messages_questions').where('mid', this.mid);

            if (data.length > 0) {
                let m = data[0];

                this.m_createdAt = m.created_at;
                this.m_updatedAt = m.updated_at;
                this.m_title = m.title;
                this.m_content = m.content;
                this.m_author = m.author;
                this.m_recipient = m.recipient;

                this.m_dataLoaded = true;
                return true;
            }
            else {
                return false;
            }
        }
        return true;
    }

    /**
     * Protected properties.
     * Ce sont tous les champs triviaux, ie qui peuvent etre récupérés en une seule requete a la BDD,
     * ce qui permet d'etre plus efficace.
     * La variable dataLoaded témoigne de si on est déja allés chercher les données.
     * ATTENTION. Ce ne sont PAS directement les resolvers, il FAUT donc qu'ils aient un nom DIFFÉRENT du nom des champs dans le schéma.
     */
    protected m_author: string
    protected m_recipient: string

    /**
     * Ci-dessous les resolvers a proprement parler.
     */

    /**
     * @memberof GraphQL.Question#
     * @function author
     * @summary Renvoie le user auteur
     * @return {Promise(User)}
     * @rights viewer du groupe recipient
     * @async
     */
    async author(args, context: Context, info): Promise<User> {
        await this.fetchData();
        return new User(this.m_author);
    }

    /**
     * @memberof GraphQL.Question#
     * @function recipient
     * @summary Renvoie le groupe destinataire
     * @return {Promise(Group)}
     * @rights viewer du groupe recipient
     * @async
     */
    async recipient(args, context: Context, info): Promise<Group> {
        await this.fetchData();
        throw "Not implemented";
    }

    /**
     * @memberof GraphQL.Question#
     * @function forAnswer
     * @summary Renvoie la réponse correspondante, si elle existe
     * @return {Promise(Answer)}
     * @rights viewer du groupe recipient
     * @async
     */
    async forAnswer(args, context: Context, info): Promise<Answer> {
        let data = await knex.select('mid').from('messages_answers').where('for_question', this.mid);
        if (data.length > 0) {
            return new Answer(data[0].mid);
        }
        return null;
    }
}

export class Answer extends Message {

    /**
     * @memberof GraphQL
     * @class Answer
     * @extends GraphQL.Message
     * @summary Resolvers des réponses
     * @classdesc Une classe représentant le type Answer du schéma.
     * Comme Apollo Server, par défaut, appelle la propriété / fonction avec le nom a résoudre, il n'y a pas besoin d'écrire les resolvers explicitement.
     * @arg {number} mid - Identifiant du message, supposé valide.
     * @rights viewer du groupe author
     */
    constructor(mid: number) {
        super(mid);
    }

    /**
     * @memberof GraphQL.Answer#
     * @function tryCreate
     * @summary Fonction qui va essayer de créer la réponse correspondante
     * @arg {number} mid - Identifiant du message, sans hypothese sur la validité.
     * @returns {Promise(Answer)} - Renvoie la Answer créée, ou null en cas d'erreur.
     * @rights viewer du groupe author
     * @async
     * @static
     */
    static async tryCreate(mid: number): Promise<Answer> {
        let m = new Answer(mid);
        if(await m.fetchData()) {
            return m;
        }
        return null;
    }

    /**
     * @memberof GraphQL.Answer#
     * @function fetchData
     * @summary Fonction qui va chercher toutes les données sur ce post privé dans la BDD, si ce n'est pas déja fait.
     * @returns {Promise(boolean)} Renvoie true si le chargement est réussi.
     * @async
     * @protected
     */
    protected async fetchData(): Promise<boolean> {
        if (!this.m_dataLoaded) {
            let data = await knex.select('created_at',
                'updated_at',
                'title',
                'content',
                'recipient', //<--- WTF ????
                'for_question').from('messages_answers').where('mid', this.mid);

            if (data.length > 0) {
                let m = data[0];

                this.m_createdAt = m.created_at;
                this.m_updatedAt = m.updated_at;
                this.m_title = m.title;
                this.m_content = m.content;
                this.m_author = m.recipient;
                this.m_forQuestion = m.for_question;

                this.m_dataLoaded = true;
                return true;
            }
            else {
                return false;
            }
        }
        return true;
    }

    /**
     * Protected properties.
     * Ce sont tous les champs triviaux, ie qui peuvent etre récupérés en une seule requete a la BDD,
     * ce qui permet d'etre plus efficace.
     * La variable dataLoaded témoigne de si on est déja allés chercher les données.
     * ATTENTION. Ce ne sont PAS directement les resolvers, il FAUT donc qu'ils aient un nom DIFFÉRENT du nom des champs dans le schéma.
     */
    protected m_author: string
    protected m_forQuestion: number

    /**
     * Ci-dessous les resolvers a proprement parler.
     */

    /**
     * @memberof GraphQL.Answer#
     * @function author
     * @summary Renvoie le groupe auteur
     * @return {Promise(Group)}
     * @rights viewer du groupe author
     * @async
     */
    async author(args, context: Context, info): Promise<Group> {
        await this.fetchData();
        throw "Not implemented";
    }

    /**
     * @memberof GraphQL.Answer#
     * @function forQuestion
     * @summary Renvoie la question correspondante
     * @return {Promise(Question)}
     * @rights viewer du groupe author
     * @async
     */
    async forQuestion(args, context: Context, info): Promise<Question> {
        await this.fetchData();
        return new Question(this.m_forQuestion);
    }
}