/**
 * @file Implémentation des requêtes GraphQL.
 * @author akka vodol
*/
import _ from 'lodash';
import { assertBinaryExpression } from 'babel-types'; //hawkspar->akka ASKIP useless
import knex from '../../db/knex_router';

import '../config_passport';

import * as connectors from './connectors/connectors';
import * as authentifiers from './connectors/authentifiers';
import MessageResolvers from './resolvers/messages';
import GroupResolvers from './resolvers/groups';

// nouveau test
/**
 * @description Résolveurs des différentes requêtes GraphQL
*/
class ChevalierError {
    returned_error: any
    name: String
    message: String
    constructor(err) {
        this.returned_error = err;
        this.name = "chevalier error";
        this.message = "Error encountered while running ldap access code : " + err.message;
    }

    toString(): String {
        return this.message;
    }
}


export const resolvers = {
    // @rights user
    Query: {

        // group queries

        allGroups: async function(root, args, context){
            let user = await authentifiers.anonymous(context.user);
            return user && connectors.getAllVisibleGroups(user);
        },

        allSimpleGroups: async function (root, args, context){
            let user = await authentifiers.anonymous(context.user);
            return user && connectors.getAllVisibleSimpleGroups(user);
        },

        group: async function(root, args, context) {
            let user = await authentifiers.anonymous(context.user);
            return user && connectors.getGroupIfVisible(user, args.uid);
        },

        simpleGroup: async function(obj, args, context){
            let user = await authentifiers.anonymous(context.user);
            return user && connectors.getSimpleGroupIfVisible(user, args.uid);
        },
        metaGroup: async function(obj, args, context){
            let user = await authentifiers.anonymous(context.user);
            return user && connectors.getMetaGroupIfVisible(user, args.uid);
        },

        /*
         * Message queries.
         */

        allAnnouncements: function(obj, args, context) {
            return knex.select().from("announcements");
        },

        allEvents(root, args, context) {
            return knex.select().from("events");
        },

        allMessages(root, args, context) {
            const events = knex.select().from("events");
            const posts = knex.select().from("posts");
            return Promise.all([events, posts]).then(res => {
                return _.flatten(res);
            });
        },


        // user queries

        user: async function(obj, args, context){
            let user = await authentifiers.anonymous(context.user);
            return user && connectors.getUser(user,args.uid);
        },

        searchTOL: (obj, args, context) => {
            const result = connectors.utilisateur.repliquerTOLdesIds({
                givenName: args.givenName,
                lastName: args.lastName,
                nickname: args.nickname,
                nationality: args.nationality,
                school: args.school,
                promotion: args.promotion,
                groups: args.groups,
                studies: args.studies,
                sport: args.sport,
                phone: args.phone,
                mail: args.mail,
                adress: args.adress,
                ip: args.ip
            });
            return result;
        },

        // viewer queries

        // member queries

        allMembers : async function(obj, args, context){
            let user = await authentifiers.member(context.user, args.from);
            return user && connectors.getGroupMemberUsers(context.user, obj.groupUID);
        },

        // speaker queries

        allRequests: async function(obj, args, context){
            let res = [];
            let user = authentifiers.admin(context.user, args.from);
            if(user){
                res = res.concat(await connectors.getUserJoinGroupRequests(user, args.from));
            }
            user = user || authentifiers.speaker(user, args.from);
            if(user){
                res = res.concat(await connectors.getGroupJoinEventRequests(user, args.from));
                res = res.concat(await connectors.getYourGroupHostEventRequests(user, args.from));
            }
            return res;
        },

        test: async function(obj, args, context){
            return connectors.getSimpleGroup(context.user, "br");
        }
    },


    Request : {
        __resolveType : function(obj){
            return obj.type;
        }
    },

    // @rights admin(obj.groupUID)
    UserJoinGroup: {
        user : (obj, args, context) => {
            return connectors.getUser(context.user, obj.useruid);
            /*return connectors.getUser(context.user, "quentin.gendre");
            if(obj.useruid === "anatole.romon"){
                return connectors.getUser(context.user, "anatole.romon").then(res => {
                    return connectors.getUser(context.user, "quentin.gendre");
                });
            }else{
                return new Promise( (resolve, reject) => {
                    resolve({givenName : "patrick"});
                });
            }*/
        }
    },

    // @rights speaker(obj.groupUID)
    GroupJoinEvent : {
        event: (obj, args, context) => {
            return connectors.getEvent(context.user, obj.eventuid);
        },
        groupWantingToJoin: (obj, args, context) => {
            return connectors.getGroup(context.user, obj.senderuid);
        }
    },

    // @rights speaker(obj.groupUID)
    YourGroupHostEvent : {
        event: (obj, args, context) => {
            return connectors.getEvent(context.user, obj.eventuid);
        },
        sender: (obj, args, context) => {
            return connectors.getGroup(context.user, obj.senderuid);
        }
    },

    // @rights user
    User : {
        groups : (obj, args, context) => {
            let result = Promise.all(obj.groups.map((grid) => {
                return connectors.getSimpleGroup(context.user,grid);
            }));

            return result.then(groups => {
                return _.filter(groups,(o) => !_.isUndefined(o));
            });
        },

    },

    // @rights user
    Mutation: {

        // Superviser mutations

        takeAdminRights : async function(obj, args, context){
            let user = await authentifiers.superviser(context.user, args.from);
            return user && await connectors.takeAdminRights(user, args.from, user.justification);
        },

        releaseAdminRights : async function(obj, args, context){
            let user = await authentifiers.superviser(context.user, args.from);
            return user && await connectors.releaseAdminRights(user, args.from, user.justification);
        },

        // Admin mutations

        createSubgroup: async function (obj, args, context){
            let user = authentifiers.admin(context.user, args.from);
            return user && connectors.createSubgroup(user, args);
        },
    },

    
    ...MessageResolvers,

    ...GroupResolvers,
};