/**
 * @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 auth from './new_connectors/authorisation';
import * as conn from './new_connectors/connection';

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) : Promise<conn.Group[]>{
            const visibleGroupSet = await auth.forViewer(context.user);
            return conn.getGroups(visibleGroupSet);
        },

        allSimpleGroups: async function (root, args, context) : Promise<conn.Group[]>{
            const visibleGroupSet = await auth.forViewer(context.user);
            return conn.getSimpleGroups(visibleGroupSet);
        },

        allMetaGroups: async function(root, args, context) : Promise<conn.Group[]>{
            const visibleGroupSet = await auth.forViewer(context.user);
            return conn.getMetaGroups(visibleGroupSet);
        },

        group: async function(root, args, context) : Promise<conn.Group>{
            if(await auth.isViewer(context.user, args.gid)){
                return conn.getGroup(args.gid);
            }else{
                return null;
            }
        },

        simpleGroup: async function(obj, args, context) : Promise<conn.Group>{
            if(await auth.isViewer(context.user, args.gid)){
                return conn.getSimpleGroup(args.gid);
            }else{
                return null;
            }
        },

        metaGroup: async function(obj, args, context) : Promise<conn.Group>{
            if(await auth.isViewer(context.user, args.gid)){
                return conn.getMetaGroup(args.gid);
            }else{
                return null;
            }
        },

        /*
         * Message queries.
         */

        allAnnouncements: async function(obj, args, context) : Promise<Object[]> {
            const visibleGroupSet = await auth.forViewer(context.user);
            return conn.allAnnouncements(visibleGroupSet);
        },

        allEvents: async function (root, args, context) : Promise<Object[]> {
            const visibleGroupSet = await auth.forViewer(context.user);
            return conn.allAnnouncements(visibleGroupSet);
        },

        // user queries

        user: async function(root, args, context){
            return conn.getUser(args.uid);
        },

        searchTOL: (root, args, context) => {
            // TODO : filter
            return conn.searchUsers(args);
        },

        test: async function(root, args, context){
            return conn.getSimpleGroup("br");
        }
    },


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

    // @rights admin(obj.groupUID)
    UserJoinGroup: {
        user : (obj, args, context) => {
            return conn.getUser(obj.useruid);
        }
    },

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

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

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

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

    },

    // @rights user
    Mutation: {

        // Superviser mutations

        takeAdminRights : async function(obj, args, context) : Promise<boolean>{
            const justification = await auth.isSupervisor(context.user, args.from);
            if(justification){
                return conn.takeAdminRights(context.user, args.from, justification);
            }else{
                return false;
            }
        },

        releaseAdminRights : async function(obj, args, context){
            await conn.releaseAdminRights(context.user, args.from);
        },

        // Admin mutations

        createSubgroup: async function (obj, args, context){
            throw new Error('Not implemented');
        },
    },

    
    ...MessageResolvers,

    ...GroupResolvers,
};