import { Injectable, Injector } from '@angular/core'
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpHeaders, HttpResponse } from '@angular/common/http'
import { RequestCacheWithMap } from '@k-services/general/svc.requestCache'
import { Observable } from 'rxjs/Rx'
import 'rxjs/add/observable/throw'
import 'rxjs/add/operator/catch'
import { tap } from 'rxjs/operators';
import { of } from 'rxjs/observable/of';

@Injectable()
export class CacheInterceptor implements HttpInterceptor {
    

    constructor(
        private cache: RequestCacheWithMap
    ) {}



    intercept(
        req: HttpRequest<any>,
        next: HttpHandler
    ): Observable<HttpEvent<any>> {


        // continue if not cachable.
        if (isCachable(req)) {
            return next.handle(req)
        }

        // Return cached response, if it's found, else make the request and cache it
        const cachedResponse = this.cache.get(req)
        return cachedResponse ?
            of(cachedResponse) : sendRequest(req, next, this.cache)

        /**
         * Get server response observable by sending request to `next()`.
         * Will add the response to the cache on the way out.
         */
        function sendRequest(
            req: HttpRequest<any>,
            next: HttpHandler,
            cache: RequestCacheWithMap): Observable<HttpEvent<any>> {
            
                // No headers allowed in npm search request
                const noHeaderReq = req.clone({ headers: new HttpHeaders() })
            
                return next.handle(noHeaderReq).pipe(
                tap(event => {

                    // There may be other events besides the response.
                    if (event instanceof HttpResponse) {
                        cache.put(req, event) // Update the cache.
                    }
                })
            )
        }

        /**
         * Checks if the request has noCache, either in the body or in the url parameters
         * 
         * @param req 
         */
        function isCachable(req) {

            if(!!req.body && !!req.body.noCache || req.urlWithParams.includes('noCache') || req.urlWithParams.includes('noLocale')) {
                return true
            } else {
                return false
            }
        }
    }
}