import * as BluebirdPromise from "bluebird";
import exceptions = require("./Exceptions");
import { UserDataStore } from "./storage/UserDataStore";
import { AuthenticationTraceDocument } from "./storage/AuthenticationTraceDocument";

const MAX_AUTHENTICATION_COUNT_IN_TIME_RANGE = 3;

export class AuthenticationRegulator {
  private userDataStore: UserDataStore;
  private lockTimeInSeconds: number;

  constructor(userDataStore: any, lockTimeInSeconds: number) {
    this.userDataStore = userDataStore;
    this.lockTimeInSeconds = lockTimeInSeconds;
  }

  // Mark authentication
  mark(userId: string, isAuthenticationSuccessful: boolean): BluebirdPromise<void> {
    return this.userDataStore.saveAuthenticationTrace(userId, isAuthenticationSuccessful);
  }

  regulate(userId: string): BluebirdPromise<void> {
    return this.userDataStore.retrieveLatestAuthenticationTraces(userId, false, 3)
      .then((docs: AuthenticationTraceDocument[]) => {
        if (docs.length < MAX_AUTHENTICATION_COUNT_IN_TIME_RANGE) {
          // less than the max authorized number of authentication in time range, thus authorizing access
          return BluebirdPromise.resolve();
        }

        const oldestDocument = docs[MAX_AUTHENTICATION_COUNT_IN_TIME_RANGE - 1];
        const noLockMinDate = new Date(new Date().getTime() - this.lockTimeInSeconds * 1000);
        if (oldestDocument.date > noLockMinDate) {
          throw new exceptions.AuthenticationRegulationError("Max number of authentication. Please retry in few minutes.");
        }

        return BluebirdPromise.resolve();
      });
  }
}