/*
 * Copyright (C) 2022 StApps
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */
import {
  TokenErrorJson,
  AuthorizationServiceConfiguration,
  RevokeTokenRequest,
  Requestor,
  JQueryRequestor,
  BasicQueryStringUtils,
  QueryStringUtils,
  AppAuthError,
  TokenError,
} from '@openid/appauth';
import {PAIATokenRequest} from './paia-token-request';
import {PAIATokenResponse, PAIATokenResponseJson} from './paia-token-response';

export class PAIATokenRequestHandler {
  constructor(
    public readonly requestor: Requestor = new JQueryRequestor(),
    public readonly utils: QueryStringUtils = new BasicQueryStringUtils(),
  ) {}

  private isTokenResponse(
    response: PAIATokenResponseJson | TokenErrorJson,
  ): response is PAIATokenResponseJson {
    return (response as TokenErrorJson).error === undefined;
  }

  performRevokeTokenRequest(
    configuration: AuthorizationServiceConfiguration,
    request: RevokeTokenRequest,
  ): Promise<boolean> {
    const revokeTokenResponse = this.requestor.xhr<boolean>({
      url: configuration.revocationEndpoint,
      method: 'GET',
      // headers: {'Content-Type': 'application/x-www-form-urlencoded'},
      data: this.utils.stringify(request.toStringMap()),
    });

    return revokeTokenResponse.then(_response => {
      return true;
    });
  }

  performTokenRequest(
    configuration: AuthorizationServiceConfiguration,
    request: PAIATokenRequest,
  ): Promise<PAIATokenResponse> {
    const tokenResponse = this.requestor.xhr<PAIATokenResponseJson | TokenErrorJson>({
      url: configuration.tokenEndpoint,
      method: 'POST',
      data: {
        patron: request.patron,
        grant_type: 'authorization_code',
        ...request.toStringMap(),
      },
      headers: {
        'Authorization': `Basic ${request.code}`,
        'Content-Type': 'application/json',
      },
    });

    return tokenResponse.then(response => {
      return this.isTokenResponse(response)
        ? new PAIATokenResponse(response)
        : Promise.reject<PAIATokenResponse>(new AppAuthError(response.error, new TokenError(response)));
    });
  }
}
