import { Observable, Subject } from 'rxjs';
import { FancyColumn, FancyGroup, FtTrigger } from './fancy-row-column.model';
import { FancyEditorInstance, FancySelection } from './fancy-selection.model';
import { EventEmitter } from '@angular/core';
import { ContextMenuItem } from '../../directives/right-click-menu/context-menu-item.model';

export const isFancyGroup = <T>(o: T | FancyGroup<T>): o is FancyGroup<T> => {
    return o && o.hasOwnProperty("groupKey") && typeof (o as FancyGroup<T>).groupKey === "string";
}
export const isNotFancyGroup = <T>(o: T | FancyGroup<T>): o is T => {
    return false == (o && o.hasOwnProperty("groupKey") && typeof (o as FancyGroup<T>).groupKey === "string");
}
export class FancySettings<T = any> {

    /**
     * Set width to 100%
     */
    public autoWidth?: boolean = true;
    /**
     * Displaying titles of each column, default as `true`
     */
    public showHeader?: boolean = true;
    /**
     * Displaying footer, default as `false`
     */
    public showFooter?: boolean = false;
    /**
     * Enable sticky footer, default as `false`
     */
    public stickyFooter?: boolean = false;
    /**
     * Displaying filter of each column, default as `true`
     */
    public showFilters?: boolean = true;
    /**
     * Displaying group side menu when group by a column, default as `false`
     */
    public showGroupsMenu?: boolean = false;

    /**
     * Allow user selecting row and hight light it, default as `true`
     */
    public allowSelection?: boolean = true;
    /**
     * Allow user drag and drop row, default as `false`
     */
    public allowDragAndDrop?: boolean = false;
    /**
     * Allow user drag and drop row, default as `false`
     */
    public allowDrag?: boolean = false;
    /**
     * When allow user drag and drop row, using drag icon instead of drag all row, default as `false`
     */
    public usingDragIcon?: boolean = false;
    /**
     * Allow user selecting multi rows, default as `false`
     */
    public multiselect?: boolean = false;
    /**
     * Allow user resizing columns, default as `true`
     */
    public resizingColumn?: boolean = true;

    /**
     * Allow user dropping files, default as `false`
     */
    public enableFileDrop?: boolean = false;

    private _columns?: FancyColumn<T>[];
    public get columns(): FancyColumn<T>[] {
        return this._columns;
    }
    public set columns(v: FancyColumn<T>[]) {
        if (v) {
            for (let i = 0; i < v.length; i++) {
                v[i] = new FancyColumn<T>({ ...v[i] });
            }
        }
        this._columns = v;
    }

    // public groups: FancyGroup[];
    public contextMenuItems?: ContextMenuItem<T>[];
    public onContextMenuOpening?: (datum: T | FancyGroup<T>, rightClickMenuItems: ContextMenuItem<T>[], selection: FancySelection<T>, event: MouseEvent) => void;
    public editorTrigger?: FtTrigger = FtTrigger.NOOP;

    public groupMissing?: string = 'N/A';

    /**
     * Using custom groups object list
     */
    public customGroups?: any[] = null;
    /**
     * The group key field name of custom groups
     */
    public customGroupKeyFieldName?: string = 'id';
    /**
     * The group value field name of custom groups
     */
    public customGroupValueFieldName?: string = 'name';
    /**
     * The group seq field name of custom groups
     */
    public customGroupSeqFieldName?: string = 'seq';

    /**
     * The group rows field name of custom groups
     */
    public customGroupRowsFieldName?: string = '';

    /**
     * Group sort rule, available types:'asc', 'desc'
     */
    public groupSortDirection?: string = 'asc';
    public groupSortFunction?: (a: FancyGroup<T>, b: FancyGroup<T>) => number;

    /**
     * For generating Group Row Description
     */
    public groupSeqPrepareFunction?: (groupKey: any) => number;
    /**
     * For generating Group Row Description
     */
    public groupValuePrepareFunction?: (groupKey: any, groupValues: T[]) => string;

    /**
     * Display group without data
     */
    public displayEmptyGroup?: boolean = false;
    /**
     * initial rows count for infinite scrolling, default as 50
     */
    public initialRows?: number = 50;
    /**
     * append rows count for infinite scrolling, default as 10
     */
    public appendRowsOnScroll?: number = 10;
    /**
     * Smooth scroll duration when using scrollToItem. Set to 0 to disable smooth scrolling.
     */
    public smoothScrollDurationMs?: number = 0;

    /**
     * adding validation for build-in editor, return `Observable<string>` error message, if valid return `null`
     */
    public addingValidation?: (obj: FancyEditorInstance<T>) => Observable<string> | string;
    /**
     * editing validation for build-in editor, return `Observable<string>` error message, if valid return `null`
     */
    public editingValidation?: (obj: FancyEditorInstance<T>) => Observable<string> | string;
    /**
     * deleting validation for build-in editor, return `Observable<string>` error message, if valid return `null`
     */
    public deletingValidation?: (obj: FancyEditorInstance<T>) => Observable<string> | string;


    /**
     * the call back buttons for easy table picker
     */
    public headerCallbackButtons?: ContextMenuItem<T>[];

    /**
     * Reload subject must be assigned from component setting
     */
    public reloadSubject?: Subject<void> = null;

    /**
     * Reassign custom group and reload table,Reload subject must be assigned from component setting
     */
    public reloadSettingSubject?: Subject<FancySettings<T>> = null;

    /**
     * The tagged row target field values, it's for `checkall` column type
     */
    public taggedValues?: any[] = [];
    /**
     * The tagged row custom row data, it's for `checkall` column type
     */
    public taggedRowData?: T[] = [];

    public dialogCssClass?: string = null;


    constructor(config: Partial<FancySettings<T>>) {
        Object.assign(this, config);
    }
}
