import {Injectable, Inject, PLATFORM_ID, Optional} from '@angular/core';
import {HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse, HttpHeaders} from '@angular/common/http';
import {Observable, of} from 'rxjs';
import {tap} from 'rxjs/operators';
import {TransferState, makeStateKey, StateKey} from '@angular/core';
import {isPlatformServer} from '@angular/common';
import {properties} from "../../environments/environment";
import {REQUEST} from "./utils/tokens";
import * as Xhr2 from 'xhr2';

Xhr2.prototype._restrictedHeaders = {};

@Injectable()
export class HttpInterceptorService implements HttpInterceptor {
  private static HTTP_WHITELIST = [];
  
  constructor(private transferState: TransferState, @Inject(PLATFORM_ID) private platformId: any, @Optional() @Inject(REQUEST) protected req: any) {
  }
  
  public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (request.method !== 'GET' || this.isService(request, HttpInterceptorService.HTTP_WHITELIST)) {
      return next.handle(request);
    }
    
    const key: StateKey<string> = makeStateKey<string>(request.url);
    
    const storedResponse = this.transferState.get<any>(key, null);
    //console.info(key, storedResponse);
    if (storedResponse) {
      const response = new HttpResponse({body: storedResponse, status: 200});
      if (!isPlatformServer(this.platformId)) {
        //console.info("browser remove: ", key);
        this.transferState.remove(key);
      }
      return of(response);
    } else {
      if (isPlatformServer(this.platformId)) {
        if(request.url.startsWith('/assets') || request.url.startsWith('assets')) {
          return of(null);
        }
        let headers = new HttpHeaders();
        if(request.withCredentials && !properties.hasMachineCache) {
          headers = headers.set('Cookie', this.req.get('Cookie'));
        }
        const authReq = request.clone({
          headers: headers
        });
        return next.handle(authReq).pipe(tap((event) => {
          //console.info("server add: ", key);
          this.transferState.set(key, (<HttpResponse<any>>event).body);
        }));
      } else {
        return next.handle(request);
      }
    }
  }
  
  isService(req: HttpRequest<any>, service: string | string[]): boolean {
    if (Array.isArray(service)) {
      return !!service.find(element => req.url.indexOf(element) !== -1);
    } else {
      return req.url.indexOf(service) !== -1;
    }
  }
  
  // public cleanRequest(requestUrl: string) {
  //   console.log("cleaned");
  //   const key: StateKey<string> = makeStateKey<string>(requestUrl);
  //   this.transferState.remove(key);
  // }
}
