import { Router } from 'aurelia-router';
import { bindable, autoinject, customElement, observable, TaskQueue } from 'aurelia-framework';
import { UIInternal } from '../../exports';
import { GridOptions } from './utilities/ag-grid-helpers';
import { FirstDataRenderedEvent, GridReadyEvent, ModelUpdatedEvent, PaginationChangedEvent } from 'ag-grid-community';
import { Guid } from './utilities/guid';

@autoinject
@customElement('custom-paging')
export class CustomPaging {
    @bindable
    gridOptions: GridOptions;

    @observable
    activePage: number;

    @observable
    totalPages: number;

    customPagingAttached: string = CUSTOM_PAGING_ATTACHED;

    private instanceId: string;

    constructor(private taskQueue: TaskQueue, private router: Router) {
        this.instanceId = new Date().toISOString();
    }

    activePageChanged(newValue, oldValue) {
        if (newValue !== oldValue) {
            this.goToPage(newValue - 1);
        }
    }

    goToPage(page: number) {
        if (this.gridOptions.api != null) {
            this.gridOptions.api.paginationGoToPage(page);
        }
    }

    private totalPagesChanged() {
        if (this.totalPages > 1) {
            // Set to previous page number, if any and if all the pages are loaded
            let previousPageNbr = this.retrievePreviousPageNbr();
            if (previousPageNbr != null && previousPageNbr <= this.totalPages) {
                this.gridOptions?.api?.paginationGoToPage(previousPageNbr - 1)
            }
        }
    }

    bind() {
        this.activePage = this.gridOptions?.api?.paginationGetCurrentPage() ?? 1;

        this.gridOptions.suppressPaginationPanel = true;

        this.gridOptions.onPaginationChanged = (event?: PaginationChangedEvent<any>) => {
            if (event.api != null) {
                this.totalPages = event.api.paginationGetTotalPages();
                let currentPage = event.api.paginationGetCurrentPage() + 1;
                if (this.activePage != currentPage) {
                    this.activePage = currentPage;
                } else {
                    UIInternal.broadcast(UIInternal.EVT_PAGINATION_CHANGE);
                    this.setCurrentSessionPagination(currentPage);
                }
            }
        };
    }

    private paginationSessionIdentifier: string;
    private get paginationSessionKey(): string {
        this.paginationSessionIdentifier ??= this.router.currentInstruction?.config?.moduleId ?? Guid.newGuid().toString();
        return [LIST_VIEW_BACK_TO_PAGE, this.paginationSessionIdentifier].join('/');
    }

    private setCurrentSessionPagination(pageNbr: number) {
        let obj = sessionStorage.getItem(this.paginationSessionKey);
        let sessionPagination: SessionPagination;
        if (obj == null) {
            // Nothing saved yet
            sessionPagination = { instanceId: this.instanceId, currentPageNbr: pageNbr };
        } else {
            sessionPagination = JSON.parse(obj);
            if (sessionPagination.instanceId == this.instanceId) {
                // Is already for current instance, update value
                sessionPagination.currentPageNbr = pageNbr;
            } else {
                // Is for previous instance, create new object and set previous
                sessionPagination = {
                    instanceId: this.instanceId,
                    currentPageNbr: pageNbr,
                    previousPageNbr: sessionPagination.currentPageNbr
                };

            }
        }
        sessionStorage.setItem(this.paginationSessionKey, JSON.stringify(sessionPagination));
    }

    private retrievePreviousPageNbr() {
        let obj = sessionStorage.getItem(this.paginationSessionKey);
        let sessionPagination: SessionPagination;
        let pageNbr: number;
        if (obj != null) {
            sessionPagination = JSON.parse(obj);
            if (sessionPagination.instanceId == this.instanceId) {
                // Is linked to current instance, take previous
                pageNbr = sessionPagination.previousPageNbr;
                // remove from sessions storage (don't execute twice)
                sessionPagination.previousPageNbr = null;
                sessionStorage.setItem(this.paginationSessionKey, JSON.stringify(sessionPagination));
            } else {
                // Is linked to previous instance, take current
                pageNbr = sessionPagination.currentPageNbr;
                this.setCurrentSessionPagination(pageNbr);
            }
        }
        return pageNbr;
    }
}

export const LIST_VIEW_BACK_TO_PAGE = "LIST_VIEW_BACK_TO_PAGE";
export const CUSTOM_PAGING_ATTACHED = "Custom-Paging-Attached";

interface SessionPagination {
    instanceId: string;
    currentPageNbr?: number;
    previousPageNbr?: number;
}