import * as O from 'fp-ts/lib/Option';
import OidcClient from 'oidc-client';
import { Lazy } from '../../../utils';
import appConfigurationQuery from './app-configuration.query';
import appConfigurationService from './app-configuration.service';
import sessionStore, { AuthenticationState } from './session.store';
export var OidcRoutes;
(function (OidcRoutes) {
  OidcRoutes["SignIn"] = "/oidc/callback";
  OidcRoutes["SignOut"] = "/oidc/logout";
  OidcRoutes["SilentRefresh"] = "/oidc/silent-refresh";
})(OidcRoutes || (OidcRoutes = {}));
export class AuthenticationService {
  constructor() {
    this.tokenQueryParameter = 'token';
    this.getHostUrl = () => appConfigurationService.getAppHostUrl();
    this.userManager = new Lazy(() => {
      const instance = new OidcClient.UserManager(this.userManagerSettings);
      instance.events.addAccessTokenExpired(async () => this.signOutRedirectAsync());
      instance.events.addUserLoaded(this.sessionUpdatedHandler);
      this.configureLogging();
      return instance;
    });
  }
  shouldPerformSignIn(query) {
    const identityReferenceToken = this.getIdentityReferenceTokenFromRoute(query);
    return O.isSome(identityReferenceToken);
  }
  isOidcRoute(urlPath) {
    return (urlPath.includes(OidcRoutes.SignIn) ||
      urlPath.includes(OidcRoutes.SignOut) ||
      urlPath.includes(OidcRoutes.SilentRefresh));
  }
  initFromRoute(urlPath, query) {
    if (this.isOidcRoute(urlPath)) {
      return;
    }
    const identityReferenceToken = this.getIdentityReferenceTokenFromRoute(query);
    if (O.isNone(identityReferenceToken)) {
      sessionStore.update({ authenticationState: AuthenticationState.Error });
      throw Error(`"${this.tokenQueryParameter}" URL query parameter is required`);
    }
    this.signInRedirectAsync(identityReferenceToken);
  }
  async signOutRedirectAsync() {
    sessionStore.update({ authenticationState: AuthenticationState.SignOutPending });
    return this.userManager.value.signoutRedirect();
  }
  async signInRedirectCallbackAsync() {
    await this.userManager.value.signinRedirectCallback();
    sessionStore.update({ authenticationState: AuthenticationState.Authenticated });
  }
  async signOutRedirectCallbackAsync() {
    await this.userManager.value.signoutRedirectCallback();
    sessionStore.update({ authenticationState: AuthenticationState.Unauthorized });
  }
  async silentRefreshCallbackAsync() {
    await this.userManager.value.signinSilentCallback();
  }
  async signInRedirectAsync(identityReferenceToken) {
    sessionStore.update({ authenticationState: AuthenticationState.SignInPending });
    return this.userManager.value.signinRedirect({
      extraQueryParams: {
        irt: identityReferenceToken.value
      }
    });
  }
  getIdentityReferenceTokenFromRoute(query) {
    const urlParams = new URLSearchParams(query);
    return O.fromNullable(urlParams.get(this.tokenQueryParameter));
  }
  sessionUpdatedHandler(user) {
    sessionStore.update({ jwt: O.fromNullable(user.access_token) });
  }
  get userManagerSettings() {
    return {
      authority: appConfigurationQuery.configuration.OidcAuthority,
      client_id: 'apollo-benefits-ui',
      redirect_uri: `${this.getHostUrl()}${OidcRoutes.SignIn}`,
      response_type: 'id_token token',
      scope: 'openid',
      post_logout_redirect_uri: `${this.getHostUrl()}${OidcRoutes.SignOut}`,
      silent_redirect_uri: `${this.getHostUrl()}${OidcRoutes.SilentRefresh}`,
      automaticSilentRenew: true,
      accessTokenExpiringNotificationTime: 10,
      filterProtocolClaims: true,
      loadUserInfo: true,
      clockSkew: 2592000.0
    };
  }
  configureLogging() {
    OidcClient.Log.logger = console;
    OidcClient.Log.level = OidcClient.Log.DEBUG;
  }
}
export default new AuthenticationService();
