import { CUSTOM_PAGING_ATTACHED } from '../elements/custom-paging';
import { Config } from '../../config';
import { autoinject, bindable, customElement, TaskQueue } from "aurelia-framework";
import { UIInternal } from '../../exports';

export interface PaginationPage {
  title: string;
  value: number;
}
@autoinject
@customElement('ui-pagination')
export class UIPagination {
  @bindable
  private currentPage: number;
  @bindable
  private totalPages: number;
  @bindable
  private paginationSize: number;
  @bindable
  private resetPageIfInvalidOnly: boolean = false;

  private displayPages: Array<PaginationPage> = [];
  private hideSinglePage: boolean = true;
  private boundaryLinks: boolean = true;
  private directionLinks: boolean = true;

  constructor(private taskQueue: TaskQueue, private config: Config) {
    this.boundaryLinks = config.globalConfig.showPaginationBoundaryLinks;
  }
  bind() {
    if (this.currentPage === undefined || this.currentPage === null || this.currentPage < 1) {
      this.currentPage = 1;
    }
    this.calculatePages();
    UIInternal.broadcast(CUSTOM_PAGING_ATTACHED);
  }
  totalPagesChanged() {
    this.resetCurrentPage();
    this.calculatePages();
  }

  paginationSizeChanged() {
    this.resetCurrentPage();
    this.calculatePages();
  }

  private resetCurrentPage() {
    if (false == this.resetPageIfInvalidOnly || this.currentPage > this.totalPages) {
      console.warn('set current page to 1 (ui-pagination)')
      this.currentPage = 1;
    }
  }

  currentPageChanged() {
    this.calculatePages();
  }

  calculatePages() {
    if (this.displayPages == null) {
      this.displayPages = new Array();
    }
    this.displayPages.splice(0);
    if (isNaN(this.paginationSize) || this.totalPages <= this.paginationSize) {
      this.displayAllPages();
    } else {
      this.limitVisiblePages();
    }
  }

  displayAllPages() {
    for (let i = 1; i <= this.totalPages; i++) {
      this.displayPages.push({
        title: i.toString(),
        value: i
      });
    }
  }

  limitVisiblePages() {
    let totalTiers = Math.ceil(this.totalPages / this.paginationSize);

    let activeTier = Math.ceil(this.currentPage / this.paginationSize);

    let start = ((activeTier - 1) * this.paginationSize) + 1;
    let end = start + this.paginationSize;

    if (activeTier > 1) {
      this.displayPages.push({
        title: '...',
        value: start - 1
      });
    }

    for (let i = start; i < end; i++) {
      if (i > this.totalPages) {
        break;
      }

      this.displayPages.push({
        title: i.toString(),
        value: i
      });
    }

    if (activeTier < totalTiers) {
      this.displayPages.push({
        title: '...',
        value: end
      });
    }
  }

  selectPage(page: number) {
    if (page < 1 || page > this.totalPages || page === this.currentPage) {
      return;
    }
    this.currentPage = page;
  }

  nextPage() {
    let page = this.currentPage + 1;
    this.selectPage(page);
  }

  previousPage() {
    let page = this.currentPage - 1;
    this.selectPage(page);
  }

  firstPage() {
    this.selectPage(1);
  }

  lastPage() {
    this.selectPage(this.totalPages);
  }
}