import { LOGGER_SERVICE_TOKEN } from '../../logger';
import * as d3 from 'd3-selection';
import { drag } from 'd3-drag';
import { ViewOperationType } from '../../model';
import { ConditionalEnableElement } from '../base/conditional-enable-element';
import { GraphStateElement } from '../shared/graph/graph-state-element';
import { AlertModalComponent } from '../../modal/alert/alert-modal.component';
import { ConfirmOperationModalComponent } from '../../modal/confirm-operation/confirm-operation-modal.component';
import { VerifyPasswordModalComponent } from '../../modal/verify-password/verify-password-modal.component';
import { ViewService } from '../../view/view.service';
export class ViewOperationElement extends ConditionalEnableElement {
    constructor(element, injector, modalService, variableCommunicator, variableStore, graphStore, permissionChecker, operationRecordService, securityChecker, localization, popupViewService, hostContainerId, el, signalRAppId) {
        super(element, permissionChecker, variableCommunicator, variableStore, localization, signalRAppId);
        this.modalService = modalService;
        this.graphStore = graphStore;
        this.operationRecordService = operationRecordService;
        this.securityChecker = securityChecker;
        this.popupViewService = popupViewService;
        this.hostContainerId = hostContainerId;
        this.el = el;
        this.touchedScreenX = 0;
        this.touchedScreenY = 0;
        this.logger = injector.get(LOGGER_SERVICE_TOKEN);
        this.viewService = injector.get(ViewService);
        this.initElement();
    }
    initElement() {
        const width = this.model.size.width;
        const height = this.model.size.height;
        this.initGraph(width, height);
        this.rootElement.append('rect').attr('id', 'StateFrame').attr('width', width).attr('height', height).attr('fill', 'transparent');
        const $dateTimeText = this.$element.find('text').last();
        const fontStyle = this.model.label.font.fontStyle;
        $dateTimeText.css('font', fontStyle + ',msyh');
        this.switchToState(0);
        this.rootElement.on('mousedown', () => {
            if (!this.isInitialized) {
                return;
            }
            this.switchToState(1);
            d3.event.preventDefault();
            if (!this.isEnable) {
                const message = !this.isGrantedPermission ? this.localization.permissiontip : this.localization.conditionIsNotMetTip;
                const modalRef = this.modalService.show(AlertModalComponent, { initialState: { alermMessage: message }, backdrop: 'static', class: 'gui-modal-dialog-position', animated: false });
                const onClosedSub = modalRef.content.onClosed.subscribe(() => {
                    modalRef.hide();
                    onClosedSub.unsubscribe();
                });
                return;
            }
        });
        this.rootElement.on('mouseup', () => {
            this.switchToState(0);
            d3.event.preventDefault();
            if (!this.isInitialized || !this.isEnable) {
                return;
            }
            if (this.model.useSecurity) {
                const modalRef = this.modalService.show(ConfirmOperationModalComponent, {
                    backdrop: 'static', class: 'gui-modal-dialog-position', animated: false
                });
                const onClosedSub = modalRef.content.onClosed.subscribe(result => {
                    modalRef.hide();
                    onClosedSub.unsubscribe();
                    if (result) {
                        this.checkElementPassword();
                    }
                });
            }
            else {
                this.checkElementPassword();
            }
        });
        if (this.model.operationType === ViewOperationType.ControlView) {
            this.rootElement.style('cursor', 'move');
            this.rootElement.call(drag().on('start', () => {
                if (!this.isEnable) {
                    this.rootElement.style('cursor', 'hand');
                    return;
                }
                if (!d3.event || !d3.event.sourceEvent) {
                    this.logger.error('[GUI]Failed to get DragEvent', d3.event);
                    return;
                }
                if (d3.event.sourceEvent.type === 'touchstart' && d3.event.sourceEvent.touches.length) {
                    this.touchedScreenX = d3.event.sourceEvent.touches[0].screenX;
                    this.touchedScreenY = d3.event.sourceEvent.touches[0].screenY;
                }
            }).on('drag', () => {
                if (!this.isEnable) {
                    this.rootElement.style('cursor', 'hand');
                    return;
                }
                if (!d3.event || !d3.event.sourceEvent) {
                    this.logger.error('[GUI]Failed to get DragEvent', d3.event);
                    return;
                }
                if (d3.event.sourceEvent.type === 'mousemove') {
                    this.moveView(d3.event.sourceEvent.movementX, d3.event.sourceEvent.movementY);
                }
                else if (d3.event.sourceEvent.type === 'touchmove' && d3.event.sourceEvent.touches.length) {
                    const movementX = d3.event.sourceEvent.touches[0].screenX - this.touchedScreenX;
                    const movementY = d3.event.sourceEvent.touches[0].screenY - this.touchedScreenY;
                    this.touchedScreenX = d3.event.sourceEvent.touches[0].screenX;
                    this.touchedScreenY = d3.event.sourceEvent.touches[0].screenY;
                    this.moveView(movementX, movementY);
                }
            }).on('end', () => this.switchToState(0)));
        }
        else {
            this.rootElement.style('cursor', 'hand');
        }
    }
    switchToState(stateId) {
        if (this.graphStateElement) {
            this.graphStateElement.switchToState(stateId);
        }
    }
    initGraph(width, height) {
        if (this.model.useGraph === true) {
            this.graphStateElement = new GraphStateElement(this.model.graphSetting, width, height, this.graphStore, this.logger);
            this.$element.prepend(this.graphStateElement.Element);
            this.graphStateElement.switchToState(0);
        }
    }
    checkElementPassword() {
        if (this.model.enablePassword) {
            const modalRef = this.modalService.show(VerifyPasswordModalComponent, { initialState: { securityChecker: this.securityChecker }, backdrop: 'static', class: 'gui-modal-dialog-position', animated: false });
            const onClosedSub = modalRef.content.onClosed.subscribe(result => {
                modalRef.hide();
                onClosedSub.unsubscribe();
                if (result) {
                    this.executeViewOperation();
                }
            });
        }
        else {
            this.executeViewOperation();
        }
    }
    executeViewOperation() {
        let operationType = this.model.version >= 5 ? this.model.operationType : ViewOperationType.ToggleView;
        operationType = operationType === undefined ? ViewOperationType.ToggleView : operationType;
        switch (operationType) {
            case ViewOperationType.ToggleView:
                this.toggleView();
                break;
            case ViewOperationType.PopupView:
                this.popView();
                break;
            case ViewOperationType.CloseView:
                this.closeView();
                break;
        }
    }
    toggleView() {
        const viewIndex = this.model.viewIndex;
        if (null != viewIndex) {
            const toggleView = this.viewService.toggleViews.get(this.el);
            if (!toggleView) {
                return;
            }
            toggleView(viewIndex, this.hostContainerId, this.el).subscribe(() => this.recordViewOperation(), error => this.logger.error(`ToggleView(${viewIndex}) failed. `, error));
        }
        else {
            this.logger.error('[GUI]Toggle View:invalid view index');
        }
    }
    popView() {
        const viewIndex = this.model.viewIndex;
        if (null != viewIndex) {
            this.popupViewService.popView(viewIndex, this.hostContainerId, this.el).subscribe(() => this.recordViewOperation(), error => this.logger.error(`ToggleView(${viewIndex}) failed. ${error}`));
            $(`#${this.hostContainerId} video`)
                .addClass('video-hidden')
                .css('visibility', 'hidden');
        }
        else {
            this.logger.error('[GUI]Toggle View:invalid view index');
        }
    }
    closeView() {
        this.popupViewService.closeView();
        $(`#${this.hostContainerId} .video-hidden`)
            .removeClass('video-hidden')
            .css('visibility', 'visible');
        this.recordViewOperation();
    }
    moveView(movementX, movementY) {
        if (isNaN(movementX) || isNaN(movementY)) {
            return;
        }
        this.popupViewService.moveView(movementX, movementY);
        this.recordViewOperation();
    }
    recordViewOperation() {
        if (this.model.isRecordOperation) {
            this.operationRecordService.record({ operationDescription: this.model.operationDescription });
        }
    }
}
