import {Injectable, OnDestroy} from '@angular/core';
import {HttpClient} from "@angular/common/http";
import {Observable, Subject} from "rxjs";
import {environment} from "../../../../environments/environment";
import {AppState} from "../app-state";
import {Router} from "@angular/router";
import {takeUntil} from "rxjs/operators";

@Injectable({
  providedIn: 'root'
})
export class ApiService implements OnDestroy {
  private _destroy$ = new Subject<boolean>()

  constructor(
    private http: HttpClient,
    private appState: AppState,
    private router: Router
  ) {
  }

  ngOnDestroy(): void {
    this._destroy$.next(true)
    this._destroy$.complete()
  }

  get<T>(url: string, needAuthentication = true, options: any = {}): Observable<T> {
    if (this.checkAuthenticated(needAuthentication, options)) {
      // @ts-ignore
      return this.http.get<string>(environment.apiUrl + url, options).pipe(takeUntil(this._destroy$))
    }
  }

  post<T>(url: string, body: any = {}, needAuthentication = true, options: any = {}): Observable<T> {
    if (this.checkAuthenticated(needAuthentication, options)) {
      // @ts-ignore
      return this.http.post<T>(environment.apiUrl + url, body, options).pipe(takeUntil(this._destroy$))
    }
  }

  put<T>(url: string, body: any = {}, needAuthentication = true, options: any = {}): Observable<T> {
    if (this.checkAuthenticated(needAuthentication, options)) {
      // @ts-ignore
      return this.http.put<T>(environment.apiUrl + url, body, options).pipe(takeUntil(this._destroy$))
    }
  }

  delete<T>(url: string, needAuthentication = true, options: any = {}): Observable<T> {
    if (this.checkAuthenticated(needAuthentication, options)) {
      // @ts-ignore
      return this.http.delete<T>(environment.apiUrl + url, options).pipe(takeUntil(this._destroy$))
    }
  }

  private checkAuthenticated(needAuthentication: boolean, httpOptions: any): boolean {
    if (needAuthentication) {
      if (!this.appState.isAuthenticated || Date.now() > this.appState.authenticationExpiration) {
        this.navigateToLogin()
        return false
      }
      httpOptions.withCredentials = true
    }
    return true
  }

  private navigateToLogin() {
    this.router.navigate(['/account/login'])
  }
}
