import { IListable } from '../interfaces/listable-interface';

export abstract class DefaultListable<T> implements IListable<T> {

    private isForSearch: boolean;
    private _elements: Array<T>;
    private _elementsAux: Array<T>;
    private _visibleElements: Array<T>;
    private _visibleRange: [number, number] = [0, 50];

    constructor(
    ) {
        this.isForSearch = false;
        this._elements = [];
        this._elementsAux = [];
        this._visibleElements = [];
    }

    /**
     *
     */
    set elements(_elements: Array<T>) {
        this._elements = _elements;
        this.visibleElements = _elements.slice(this._visibleRange[0], this._visibleRange[1]);
    }

    /**
     *
     */
    get elements() {
        return this._elements;
    }

    /**
     *
     */
    set visibleElements(_visibleElements: Array<T>) {
        this._visibleElements = _visibleElements;
    }

    /**
     *
     */
    get visibleElements() {
        return this._visibleElements;
    }

    /**
     *
     */
    add(T: any): void {
        this._elements.push(T);
    }

    /**
     *
     */
    remove(T: any): void {
        let index = this.elements.indexOf(T);
        
        this._elements.splice(index, 1);
        this._visibleElements.splice(index, 1);
    }

    /**
     *
     */
    get(T: any): T {
        let index = this.elements.indexOf(T);
        return this._elements[index];
    }

    /**
     *
     */
    list(): Array<T> {
        return this._elements;
    }

    /**
     *
     */
    search(event: any): void {
        let value: string = event.target.value;
        this._elements = this._elementsAux;

        this.elements = this.elements.filter(item => {
            return (item as any).name.toLowerCase().indexOf(value.toLowerCase()) > -1;
        });
    }

    /**
     *
     */
    toggleSearch(): void {
        this.isForSearch = !this.isForSearch;

        if (this.isForSearch) {
            this._elementsAux = this.elements;
        } else {
            this._elements = this._elementsAux;
        }
    }

    /**
     *
     */
    isSearching(): boolean {
        return this.isForSearch;
    }

    /**
     *
     */
    seekRange(): void {
        this._visibleRange[0] = this._visibleRange[1];
        this._visibleRange[1] = this._visibleRange[1] + 50;

        this._visibleElements = this._visibleElements.concat(this._elements.slice(this._visibleRange[0], this._visibleRange[1]));
    }

    isToSeek(): boolean {
        return this._visibleRange[1] >= this.elements.length;
    }
}
