import LoggerFactory from './logger/LoggerFactory';
import ILogger from './logger/LoggerInterface';
import PlatformDetectionService from './PlatformDetection.service';
import { AuthenticationResponse, PhenixWebSocket } from './net/websockets/PhenixWebSocket';
import { PhenixWebSocketMessage } from './net/websockets/PhenixWebSocketMessage';
import UserStoreService from './user-store';

//TEMPORARY
import config from '../config';

class AuthenticationService {
  private static readonly _instance = new AuthenticationService();
  private readonly _logger: ILogger = LoggerFactory.getLogger('AuthenticationService');
  private _token: string | null = null;
  private _phenixWebSocket: PhenixWebSocket;

  public static getInstance(): AuthenticationService {
    return AuthenticationService._instance;
  }

  constructor() {
    const backenUrl = 'wss://pcast-stg.phenixrts.com/ws';
    this._phenixWebSocket = new PhenixWebSocket(backenUrl);
  }

  get sessionId(): string | null {
    return this._phenixWebSocket.sessionId;
  }

  get token(): string | null {
    return this._token;
  }

  async authenticate(applicationId: string, secret: string): Promise<AuthenticationResponse> {
    const authenticate = {
      // @ts-expect-error TODO(AZ): phenix-web-proto does not have Typescript types defined definition
      apiVersion: this._phenixWebSocket.getApiVersion(), // TODO(AZ): add types for phenix-proto-web
      clientVersion: config.controlCenterVersion,
      deviceId: '',
      platform: PlatformDetectionService.platform,
      platformVersion: PlatformDetectionService.platformVersion,
      browser: PlatformDetectionService.browser,
      browserVersion: PlatformDetectionService.version,
      applicationId,
      authenticationToken: secret,
      sessionId: this.sessionId
    };

    try {
      const authenticationResponse = await this._phenixWebSocket.sendMessage(PhenixWebSocketMessage.Authenticate, authenticate);

      if (authenticationResponse.status === 'ok') {
        this._phenixWebSocket.sessionId = authenticationResponse.sessionId;
        await UserStoreService.set('applicationId', applicationId);
        await UserStoreService.set('secret', secret);
      }

      return authenticationResponse;
    } catch (error) {
      this._logger.error('Authentication failed [%s]', error);

      throw error;
    }
  }

  public async signout(): Promise<void> {
    await this._phenixWebSocket.sendMessage(PhenixWebSocketMessage.Bye, {
      sessionId: this.sessionId,
      reason: 'signout'
    });
  }
}

export default AuthenticationService.getInstance();
