import { HttpRequest, HttpResponse, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { Observable, of, throwError } from 'rxjs';
import { delay, mergeMap, materialize, dematerialize } from 'rxjs/operators';

import { Injectable } from '@angular/core';
import { SortField, DIRECTION } from '@xdf/commons';


const basePath = '/service/reservations';

const tableData: Array<any> = [
    {
        id: 1,
        passenger: "Victoria Abad Torrez",
        ticketType: "Economy",
        travelClass: "Economy",
        status: "RESERVATED",
    },
    {
        id: 2,
        passenger: "Paola Abad Torrez",
        ticketType: "Economy",
        travelClass: "Economy",
        status: "PAID",
    },
    {
        id: 3,
        passenger: "Juan Perez",
        ticketType: "Economy",
        travelClass: "Economy",
        status: "CANCELLED",
    }
];

@Injectable()
export class ReservationFakeBackendInterceptor implements HttpInterceptor {
    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        const { url, method, headers, body } = request;

        return of(null)
            .pipe(mergeMap(handleRoute))
            .pipe(materialize())
            .pipe(delay(10))
            .pipe(dematerialize());

        function handleRoute() {

            switch (true) {
                case url.endsWith(basePath + '/page') && method === 'POST':
                    return pagination(body);
                case url.indexOf(basePath + '/connection/data') !== -1 && method === 'GET ':
                    return ok({});
                case url.indexOf(basePath + '/') !== -1 && method === 'GET':
                    return by(url)
                case url.indexOf(basePath + '/') !== -1 && method === 'DELETE':
                    return deleteById(url);
                case url.indexOf(basePath + '/create') !== -1 && method === 'POST':
                    return save(body);
                case url.indexOf(basePath + '/edit') !== -1 && method === 'PUT':
                    return edit(body, url);
                default:
                    // pass through any requests not handled above
                    return next.handle(request);
            }
        }

        function edit(data: any, url: string) {
            const id = parseInt(url.split('/').pop());
            const index = tableData.findIndex(x => x.id === id);
            data.id = id;
            tableData[index] = data;
            return ok(data);
        }

        function save(data: any) {
            const id = tableData.length + 1;
            data.id = id;
            tableData.push(data);
            return ok(data);
        }

        function deleteById(url) {
            const id = parseInt(url.split('/').pop());
            const index = tableData.findIndex(x => x.id === id);
            tableData.splice(index, 1);
            return ok();
        }

        function by(url: string) {
            const id = parseInt(url.split('/').pop());
            const by = tableData.find(x => x.id === id);
            return ok(by);
        }

        function pagination(dataRecibida: any) {
            dataRecibida.totalItems = tableData.length;

            const pageNumber = dataRecibida.currentPage;
            const pageSize = dataRecibida.itemsPerPage ? dataRecibida.itemsPerPage : 5;

            dataRecibida.totalPages = Math.ceil(dataRecibida.totalItems / pageSize);

            if (dataRecibida.sortFields.length > 0) {
                const sortField: any = dataRecibida.sortFields[0];
                if (sortField.direction === DIRECTION.asc) {
                    tableData.sort((a, b) => {
                        if (JSON.stringify(a[sortField.field]) > JSON.stringify(b[sortField.field])) {
                            return 1;
                        } else if (JSON.stringify(a[sortField.field]) < JSON.stringify(b[sortField.field])) {
                            return -1;
                        }
                        return 0;
                    });
                } else {
                    tableData.sort((a, b) => {
                        if (JSON.stringify(a[sortField.field]) < JSON.stringify(b[sortField.field])) {
                            return 1;
                        } else if (JSON.stringify(a[sortField.field]) > JSON.stringify(b[sortField.field])) {
                            return -1;
                        }
                        return 0;
                    });
                }
            }

            dataRecibida.data = tableData.slice(pageNumber * pageSize, (pageNumber + 1) * pageSize);

            return ok(dataRecibida);
        }


        function ok(bodyContent?: any) {
            return of(new HttpResponse({ status: 200, body: bodyContent }));
        }

        function error(message: string) {
            return throwError({ error: { message } });
        }
    }
}
