import { Injectable } from "@angular/core";
import {
  getMeQuery,
  getAccountQuery,
  getAccountKeysQuery,
  modifyAvatarNameQuery,
  modifyAvatarQuery,
  editTwoFactorModeQuery,
  prepareEditEmailQuery,
  editEmailQuery,
  getTwoFactorModeQuery,
  getAllAccountIdQuery,
} from "./querys";
import { ServerRestApiService } from "../services/server-rest-api.service";
import { AuthService } from "./auth.service";
import { PeerAccountKeyring } from "../crypto/keyring/account_peer";
import {
  AccountAvatarRecord,
  AccountKeysRecord,
  MeRecord,
  UserRole,
} from "./query-records/account-records";
@Injectable({
  providedIn: "root",
})
export class AccountService {
  constructor(
    private serverRestApiService: ServerRestApiService,
    private authService: AuthService
  ) {}

  private cachedPeerKeyring: PeerAccountKeyring[] = [];

  public getMe(): Promise<MeRecord> {
    return this.serverRestApiService.query({ query: getMeQuery });
  }

  public getAccount(id): Promise<AccountAvatarRecord> {
    return this.serverRestApiService.query({
      query: getAccountQuery,
      variables: {
        id,
      },
    });
  }

  /**
   * Get the all direct contact from your workspace.
   */
  public getAllAccount(): Promise<AccountAvatarRecord[]> {
    return this.serverRestApiService
      .query({
        query: getAllAccountIdQuery,
      })
      .then((ids: string[]) => {
        let promises = [];

        for (let i = 0; i < ids.length; i++) {
          // it should get them from the cache, so this happening immediatly, but a promise anyway
          promises.push(
            this.serverRestApiService.query({
              query: getAccountQuery,
              variables: { id: ids[i] },
            })
          );
        }

        return Promise.all(promises).then((allValue) => {
          return allValue;
        });
      });
  }

  public getAccountKeys(id): Promise<AccountKeysRecord> {
    return this.serverRestApiService.query({
      query: getAccountKeysQuery,
      variables: {
        id,
      },
    });
  }

  public getPeerKeyring(accountId): Promise<PeerAccountKeyring> {
    if (accountId in this.cachedPeerKeyring) {
      return Promise.resolve(this.cachedPeerKeyring[accountId]);
    } else {
      return this.getAccountKeys(accountId).then((keys) => {
        return PeerAccountKeyring.load(
          accountId,
          keys.encryptingPublicEc,
          keys.encryptingPublicEcSignature,
          keys.signingPublicEc,
          keys.trust,
          this.authService.getSelfAccountKeyring()
        ).then((peer_kr) => {
          this.cachedPeerKeyring[accountId] = peer_kr;
          return peer_kr;
        });
      });
    }
  }

  public getAvatar(userId: string): Promise<Object> {
    return this.serverRestApiService.query({
      query: getAccountQuery,
      variables: {
        id: userId,
      },
    });
  }

  public setAvatar(avatarImage): Promise<any> {
    return this.serverRestApiService.mutate({
      query: modifyAvatarQuery,
      variables: {
        image: avatarImage,
      },
    });
  }

  public changeAvatarName(avatarName: string): Promise<boolean> {
    return this.serverRestApiService.mutate({
      query: modifyAvatarNameQuery,
      variables: {
        name: avatarName,
      },
    });
  }

  public get2FA(): Promise<any> {
    return this.serverRestApiService.query({
      query: getTwoFactorModeQuery,
    });
  }

  public set2FA(enabled: boolean): Promise<boolean> {
    var mode = enabled ? 10 : 0;
    let params = {
      mode
    };
    if (localStorage.getItem('lang')){
      params['locale'] = localStorage.getItem('lang');
    }

    return this.serverRestApiService.mutate({
      query: editTwoFactorModeQuery,
      variables: params,
    });
  }

  public prepareEditEmail(newEmail: string): Promise<boolean> {
    let params = {
      email: newEmail
    };

    if (localStorage.getItem('lang')){
      params['locale'] = localStorage.getItem('lang');
    }

    return this.serverRestApiService.mutate({
      query: prepareEditEmailQuery,
      variables: params,
    });
  }

  public editEmail(token: string): Promise<boolean> {
    let params = {
      token
    };

    if (localStorage.getItem('lang')){
      params['locale'] = localStorage.getItem('lang');
    }
    return this.serverRestApiService.mutate({
      query: editEmailQuery,
      variables: params,
    });
  }

  public isCurrentUserInRole(role: UserRole, me: MeRecord): boolean{
    return me.scopes.some(scope => scope == role);
  }
}

