/* Copyright CloudLinux Zug GmbH 2010-2017 All Rights Reserved
 *
 * Licensed under CLOUD LINUX LICENSE AGREEMENT
 * http://cloudlinux.com/docs/LICENSE.TXT
 */

import { Input } from '@angular/core';
import { Column } from './column';
import { Sorter } from './sorter';
import { Row } from './row';
import { Loader, LoaderSelector } from './loader';
import { ConvertFormat } from './types';
import { AppState } from '../app.service';
import { InstanceInjector } from '../services/instance-injector';

declare var jQuery: any;

export class Grid {
    @Input() columns: Array<Column> = [];
    @Input() public oddEven: boolean = true;

    sorter: Sorter;
    key: string = '';
    directionOfSorting: number = 1; // 1 direct sorting, -1 reverse sorting
    noFoundText: string = 'NO RESULT FOUND';
    rowsOnPage: number;
    originRows: Array<Row>;
    loadMoreCount: number | boolean;
    loadedRowCount: number;
    loaderSelector: LoaderSelector = null;
    pagination: {}[];
    maxPage: number;
    _rows: Array<Row>;

    private _loading: boolean = false;
    private _checkedAllRow: boolean = false;
    private _totalCount: number = 0;
    private _noFound: boolean = false;

    set rows(value: Array<Row>) {
        let sortByColumn;
        if (Array.isArray(this.columns)) {
            this.columns.forEach(item => {
                if (item.name === this.key) sortByColumn = item.name;
            });
        } else {
            sortByColumn = this.columns[this.key];
        }
        this.originRows = value;
        if (!!this.rowsOnPage && this.rowsOnPage > 0) {
            this.goToPage(this.currentPage);
        } else if (!!this.loadMoreCount && this.loadMoreCount > 0) {
            this.reloadMore();
        } else {
            this._rows = value;
        }
        if (value && sortByColumn)
            this.formatBasedSort(sortByColumn.convertToFormat, this.key, false);
    }
    get rows(): Array<Row>{
        return this._rows;
    }

    public set noFound(val: boolean) {
        this._noFound = val;
    }

    public get noFound(): boolean {
        return (this.originRows && this.originRows.length === 0);
    }

    set totalCount(value: number) {
        this._totalCount = value;
        this.maxPage = Math.ceil(value / Number(this.rowsOnPage));
        if (this._currentPage !== 1 && this._currentPage > this.maxPage) {
            this._currentPage = this.maxPage;
        }
    }

    get totalCount(): number {
        return this._totalCount;
    }

    private _currentPage: number = 1;

    set currentPage(value: number) {
        this._currentPage = value;
        this.reload();
    }

    get currentPage(): number {
        return this._currentPage;
    }

    constructor(public appState: AppState) {
        this.sorter = new Sorter();
        this.key = '-'; // unexpected default value
    }

    reload() {
        if (!!this.loadMoreCount && this.loadMoreCount > 0) {
            this.reloadMore();
        } else {
            this.defineTotalCount();
            this._rows = this.slice(this.originRows);
            this.pagination = this.preparePagination();
        }
    }

    reloadMore() {
        this._rows = this.originRows.slice(0, this.loadedRowCount);
    }

    defineTotalCount() {
        if (typeof this.originRows !== 'undefined'
            && typeof this.originRows.length !== 'undefined'
        ) {
            this.totalCount = this.originRows.length;
        }
    }

    formatBasedSort(
        convertToFormat: ConvertFormat,
        key: string = '',
        changeDirection: boolean = true
    ){
        try {
            if (key) {
                if (changeDirection) {
                    if (key === this.key) {
                        this.directionOfSorting *= -1;
                    } else {
                        this.directionOfSorting = 1;
                    }
                }
                this.key = key;
            }
            if (this.key === '-') {
                return;
            }
            this.sorter.sort(
                this.key, this.originRows,
                this.directionOfSorting, convertToFormat
            );
            this.reload();
        } catch (e){/*
            if there no columns, error will be thrown
        */}
    }

    // TODO remove old sort
    sort(
        key = '',
        toBytes: boolean = false,
        convertToFormat: ConvertFormat = null,
        changeDirection = true
    ) {
        console.warn('sort is deprecated');
        if (toBytes) convertToFormat = 'byte-amount';
        this.formatBasedSort(convertToFormat, key, changeDirection);
    }

    /**
     * Set pagination.
     *
     * @param value
     * @returns {any[]}
     */
    slice(value: any[]) {
        if (typeof this.currentPage !== 'undefined'
            && typeof this.rowsOnPage !== 'undefined'
        ) {
            let self = this;
            return value.filter(function(row, index) {
                let startPosition = (self.currentPage - 1) * self.rowsOnPage;
                return (
                    index >= startPosition
                    && index < startPosition + self.rowsOnPage
                );
            });
        }
        return value;
    }

    public goToPage(page: number) {
        if (page) {
            this.currentPage = page;
        }
    }

    public goToPrevPage() {
        if (this.currentPage > 1) {
            this.currentPage--;
        }
    }

    public goToNextPage() {
        if (this.currentPage < this.maxPage) {
            this.currentPage++;
        }
    }

    public preparePagination(): {}[] {
        if (this.maxPage > 7) {
            if (this.currentPage <= 4) {
                return [
                    {title: '1',                  value: 1},
                    {title: '2',                  value: 2},
                    {title: '3',                  value: 3},
                    {title: '4',                  value: 4},
                    {title: '5',                  value: 5},
                    {title: '...',                value: null},
                    {title: String(this.maxPage), value: this.maxPage},
                ];
            } else if (this.currentPage > (this.maxPage - 4)) {
                return [
                    {title: '1',                      value: 1},
                    {title: '...',                    value: null},
                    {title: String(this.maxPage - 4), value: this.maxPage - 4},
                    {title: String(this.maxPage - 3), value: this.maxPage - 3},
                    {title: String(this.maxPage - 2), value: this.maxPage - 2},
                    {title: String(this.maxPage - 1), value: this.maxPage - 1},
                    {title: String(this.maxPage),     value: this.maxPage},
                ];
            } else {
                return [
                    {title: '1',   value: 1},
                    {title: '...', value: null},
                    {
                        title: String(this.currentPage - 1),
                        value: this.currentPage - 1
                    },
                    {title: String(this.currentPage), value: this.currentPage},
                    {
                        title: String(this.currentPage + 1),
                        value: this.currentPage + 1
                    },
                    {title: '...', value: null},
                    {title: String(this.maxPage), value: this.maxPage},
                ];
            }
        } else {
            let res = [];
            for (let i = 1; i <= this.maxPage; i++) {
                res.push({title: String(i), value: i});
            }
            return res;
        }
    }

    set loading(value: boolean) {
        if (this.loaderSelector && value !== this._loading) {
            this._loading = value;
            setTimeout(() => {
                if (this.appState && !this.loaderSelector.showBigLoader) {
                    this.appState.set('menuLoader', value);
                    InstanceInjector.loadingBarServiceInstance[value ? 'start' : 'complete']();
                }
            });
            Loader[
                this.loaderSelector.showBigLoader ? '__switchBigLoader' : '__switchBlockingWrapper'
                ](jQuery(this.loaderSelector.selector), value);
        }
    }

    get loading() {
        return this._loading;
    }

    public anyEditing() {
        return this.rows.some(row => row.editing);
    }

    public anyValue(column: string) {
        return this.rows.some(row =>
          row.cells[column] ? row.cells[column].lines.some(line => line.value !== '-') : false);
    }

    public loadMore() {
        if (!!this.originRows && this.loadedRowCount < this.originRows.length) {
            this.loadedRowCount += Number(this.loadMoreCount);
            this._rows = this.originRows.slice(0, this.loadedRowCount);
        }
    }

    public get remainingRowCount(): {} {
        let count = this.originRows.length - this.loadedRowCount;
        return {count: (count < 10) ? count : 10};
    }

    public get showLoadMore() {
        return (
            this.loadMoreCount && this.loadMoreCount > 0
            && this.originRows && this.originRows.length
            && this.loadedRowCount < this.originRows.length
        ) || false;
    }

    public set checkedAllRow(val: boolean) {
        this._checkedAllRow = val;
        let numberOfUnchecked
            = this.originRows.filter(row => !row.checked).length;
        if (numberOfUnchecked !== 1 || val === true) {
            this.originRows.forEach((row) => {
                row.checked = val;
            });
        }
    }

    public get checkedAllRow(): boolean {
        return this.originRows.every((row) => {
            return row.checked;
        });
    }

    public get numberOfChecked(): number {
        if (!this.originRows) return 0;
        return this.originRows.filter(row => row.checked).length;
    }
}





