import { Directive, ElementRef, HostListener, Input, AfterContentChecked } from '@angular/core';

import { ModificationsService, ModificationRecord, ModificationType } from './modifications.service';
import { SessionsService } from './sessions.service';
import { TreeService } from './tree.service';

@Directive( {
    selector: '[orderingLists]'
} )
export class OrderingDirective implements AfterContentChecked {
    private _draggingElement: HTMLElement;
    private _droppedElement: HTMLElement;
    private _dropSucceded: boolean;
    private _isInsideContainer: boolean;
    @Input() node;
    @Input() activeSession;

    constructor(private element: ElementRef,
                private modsService: ModificationsService,
                private sessionsService: SessionsService,
                private treeService: TreeService) { }

    ngAfterContentChecked() {
        this.markDraggable();
        //console.log(this.element)
    }

    @HostListener( 'dragstart', ['$event'] )
    dragStart( event ) {
        //console.log("dragStart");
        this.savePositions( 'dragIndex' );
        this._draggingElement = this.getDraggableElement( event );
        event.dataTransfer.setDragImage(this._draggingElement.firstElementChild, event.offsetX, event.offsetY);
        this._dropSucceded = false;
        this._isInsideContainer = true;

        /* Firefox hack */
        event.dataTransfer.setData('text', 'bad firefox');
    }

    @HostListener( 'dragend', ['$event'] )
    dragEnd( event: MouseEvent ) {
        //console.log("dragEnd");
        if ( !this._dropSucceded ) {
            this.cancelDragging();
        }
        event.preventDefault();
    }

    @HostListener( 'dragover', ['$event'] )
    dragOver( event: MouseEvent ) {
        //console.log("dragOver");
        // Required to receive "drop"" event
        event.preventDefault();
    }

    @HostListener( 'drag', ['$event'] )
    drag( event ) {
        //console.log("drag");
        // Check if mouse is outside container or not
        const divCoords = this.element.nativeElement.getBoundingClientRect();
        const inside = ( event.clientX >= divCoords.left && event.clientX <= divCoords.right && event.clientY >= divCoords.top && event.clientY <= divCoords.bottom );
        // Check if mouse mouves outisde container
        if ( this._isInsideContainer && !inside ) {
            this.cancelDragging();
        }

        this._isInsideContainer = inside;
    }

    @HostListener( 'dragenter', ['$event'] )
    dragEnter( event: MouseEvent ) {
        //console.log("dragEnter");
        const element: HTMLElement = this.getDraggableElement( event );
        if ( element && element.attributes ) {
            const draggingIndex = this._draggingElement.dataset['index'];
            const dropIndex = element.dataset['index'];

            if ( draggingIndex !== dropIndex ) {
                // Move dragging ghost element at its new position
                if ( draggingIndex > dropIndex ) {
                    this.element.nativeElement.insertBefore( this._draggingElement, element );
                } else {
                    this.element.nativeElement.insertBefore( this._draggingElement, element.nextSibling );
                }
                this.markDraggable();
            }
        }

        event.preventDefault();
    }

    @HostListener( 'drop', ['$event'] )
    drop( event: MouseEvent ) {
        //console.log("drop");
        this._dropSucceded = true;
        //console.log("moving " + this._draggingElement.dataset.dragIndex + " instead of " + this._draggingElement.dataset.index);
        let lastIndex = -1;
        let hasLast = false;
        let maintainLast = (this.node['info']['type'] == 16);
        let nodes = this.treeService.nodesToShow(this.activeSession, this.node);
        for ( let i = 0; i < this.element.nativeElement.childElementCount; i++ ) {
            let element = this.element.nativeElement.children[i];
            if (i == element.dataset.dragIndex) {
                /* no change */
                continue;
            }
            nodes[element.dataset.dragIndex]['order'] = i;
            if (maintainLast) {
                /* maintain last flag in lists, it is not important to maintain it in leaflist,
                 * since it is enough to have it just present in one of them */
                if ('last' in nodes[element.dataset.dragIndex]) {
                    hasLast = true;
                    delete nodes[element.dataset.dragIndex]['last'];
                } else if (i == this.element.nativeElement.childElementCount - 1) {
                    lastIndex = element.dataset.dragIndex;
                }
            }
        }
        if (hasLast) {
            nodes[lastIndex]['last'] = true;
        }

        let parent = this.treeService.nodeParent(this.activeSession, this.node);
        if (!('new' in parent)) {
            let path = this.treeService.pathCutPredicate(this.node['path'])
            let record = this.modsService.createModificationsRecord(this.activeSession, path);
            if (!('type' in record)) {
                /* new record */
                record['type'] = ModificationType.Reorder;
                record['reorder'] = [];
                for (let i in nodes) {
                    record['reorder'].push(Number(i));
                }
            }
            let move = record['reorder'][this._draggingElement.dataset.dragIndex];
            record['reorder'].splice(this._draggingElement.dataset.dragIndex, 1);
            record['reorder'].splice(this._draggingElement.dataset.index, 0, move);

            //console.log(record['reorder']);

            let same = true;
            for (let item of nodes) {
                if (item['order'] != record['reorder'][item['order']]) {
                    same = false;
                    break;
                }
            }
            if (same) {
                this.modsService.removeModificationsRecord(this.activeSession, path);
            }
        }
        this.sessionsService.storeSessions();
        event.preventDefault();
    }

    private markDraggable() {
        for ( let i = 0; i < this.element.nativeElement.childElementCount; i++ ) {
            let element = this.element.nativeElement.children[i];
            element.draggable = true;
            element.dataset.index = i;
        }
    }

    private savePositions( attribute ) {
        for ( let i = 0; i < this.element.nativeElement.childElementCount; i++ ) {
            let element = this.element.nativeElement.children[i];
            element.dataset[attribute] = i;
        }
    }

    private getElementAt( attribute, index ) {
        for ( let i = 0; i < this.element.nativeElement.childElementCount; i++ ) {
            let element = this.element.nativeElement.children[i];
            if ( parseInt( element.dataset[attribute], 10 ) === index ) {
                return element;
            }
        }
        return null;
    }

    private cancelDragging() {
        let index = this.element.nativeElement.childElementCount - 1;
        // Get last element
        let beforeElement = this.getElementAt( 'dragIndex', index );

        while ( index > 0 ) {
            const element = this.getElementAt( 'dragIndex', index - 1 );
            this.element.nativeElement.insertBefore( element, beforeElement );

            beforeElement = element;
            index--;
        }
    }

    private getDraggableElement( event ): HTMLElement {
        let element: HTMLElement = <HTMLElement>event.target;
        while ( element && element.attributes && !element.attributes['draggable'] ) {
            element = <HTMLElement>element.parentNode;
        }
        return element;
    }
}
