import { Injectable } from '@angular/core';
import {
  createResourceGroupQuery,
  deleteResourceGroupQuery,
  editResourceGroupNameQuery,
  editResourceGroupOrderingQuery,
  editResourceGroupClosedQuery,
  getAllSidebarGroupQuery,
  getSidebarUngrouppedQuery,
  getSidebarGroupQuery,
  getSidebarResourceQuery,
  editRoomPlacementQuery,
  editDialoguePlacementQuery,
  getSidebarGrantedRoomsQuery,
  getSidebarRejectedRoomsQuery,
  getSidebarNewsQuery,
} from './querys';
import { ResourceGroupCrypto } from '../crypto/top/resource-group';
import { AuthService } from './auth.service';
import { ServerRestApiService } from '../services/server-rest-api.service';
import { ID } from './query-records/common-records';
import {
  ResourceType,
  SidebarGroup,
  SidebarResource,
  SidebarNews,
} from './query-records/sidebar-records';

@Injectable({
  providedIn: 'root',
})
export class SidebarService {
  constructor(
    private serverRestApiService: ServerRestApiService,
    private authService: AuthService
  ) {}

  public getAllSidebarGroup(): Promise<SidebarGroup[]> {
    return this.serverRestApiService.query({
      query: getAllSidebarGroupQuery,
    });
  }

  /**
   * Concat all the group and oungroupped resources
   * @returns
   */
  public getAllResource(): Promise<SidebarResource[]> {
    return Promise.all([this.getAllSidebarGroup(), this.getSidebarUngroupped()]).then(
      ([group, ungroupped]) => {
        let list: SidebarResource[] = [];

        group.forEach((g) => {
          list = list.concat(g.resources);
        });

        list = list.concat(ungroupped);

        return list;
      }
    );
  }

  public getSidebarUngroupped(): Promise<SidebarResource[]> {
    return this.serverRestApiService.query({
      query: getSidebarUngrouppedQuery,
    });
  }

  public getGroup(id: ID): Promise<SidebarGroup> {
    return this.serverRestApiService.query({
      query: getSidebarGroupQuery,
      variables: { id },
    });
  }

  // mutations with the resource group -------------------------------------------
  public createGroup(name: string) {
    return this.serverRestApiService.mutate({
      query: createResourceGroupQuery,
      variables: {
        name,
      },
      encrypt: (variables, extra) => {
        return ResourceGroupCrypto.encrypt(
          variables['name'],
          this.authService.getSelfAccountKeyring()
        ).then((encryptedName) => {
          variables['name'] = encryptedName;
          return variables;
        });
      },
    });
  }

  public deleteGroup(id) {
    return this.serverRestApiService.mutate({
      query: deleteResourceGroupQuery,
      variables: {
        groupId: id,
      },
    });
  }

  public editGroupName(id, name: string): Promise<any> {
    return this.serverRestApiService.mutate({
      query: editResourceGroupNameQuery,
      variables: {
        groupId: id,
        name,
      },
      encrypt: (variables, extra) => {
        return ResourceGroupCrypto.encrypt(
          variables['name'],
          this.authService.getSelfAccountKeyring()
        ).then((encryptedName) => {
          variables['name'] = encryptedName;
          return variables;
        });
      },
    });
  }

  public editGroupOrdering(id, ordering: number) {
    return this.serverRestApiService.mutate({
      query: editResourceGroupOrderingQuery,
      variables: {
        groupId: id,
        ordering,
      },
    });
  }

  public editGroupClosed(id, closed: boolean) {
    return this.serverRestApiService.mutate({
      query: editResourceGroupClosedQuery,
      variables: {
        groupId: id,
        closed,
      },
    });
  }

  public getResource(id): Promise<SidebarResource> {
    return this.serverRestApiService.query({
      query: getSidebarResourceQuery,
      variables: {
        id,
      },
    });
  }

  public editPlacement(id: ID, groupId: ID, ordering: number, type: ResourceType) {
    if (type == ResourceType.ROOM) {
      return this.serverRestApiService.mutate({
        query: editRoomPlacementQuery,
        variables: {
          roomId: id,
          ordering,
          groupId,
        },
      });
    } else {
      return this.serverRestApiService.mutate({
        query: editDialoguePlacementQuery,
        variables: {
          peerId: id,
          ordering,
          groupId,
        },
      });
    }
  }

  public getSidebarNews(): Promise<SidebarNews> {
    return this.serverRestApiService.query({
      query: getSidebarNewsQuery,
    });
  }

  public getGrantedRooms(): Promise<ID[]> {
    return this.serverRestApiService.query({
      query: getSidebarGrantedRoomsQuery,
    });
  }

  public getRejectedRooms(): Promise<ID[]> {
    return this.serverRestApiService.query({
      query: getSidebarRejectedRoomsQuery,
    });
  }
}
