var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
import { Component, ElementRef, EventEmitter, Inject, Injector, Input, Output } from '@angular/core';
import { isNaN as lodashIsNaN, isEqual } from 'lodash';
import { BsModalService } from 'ngx-bootstrap/modal';
import { LOCALIZATION } from '../localization';
import { Size } from '../model';
import { DisplayMode, GlobalSettings, ViewResizeMode } from '../settings';
import { GuiHost } from './gui-host';
import { Guid } from '../utils/guid';
import { ViewService } from '../view/view.service';
let GuiComponent = class GuiComponent {
    constructor(el, localization, injector, bsModalService) {
        this.el = el;
        this.localization = localization;
        this.injector = injector;
        this.bsModalService = bsModalService;
        this.loadFailed = new EventEmitter();
        this.loaded = new EventEmitter();
        this.lastScale = 1;
        this.isMobileMode = false;
        this.globalSettings = this.injector.get(GlobalSettings);
        this.viewService = injector.get(ViewService);
    }
    get viewResizeMode() {
        switch (this.resizeMode) {
            case 'HorizontalUniform':
                return ViewResizeMode.HorizontalUniform;
            default:
                return ViewResizeMode.Uniform;
        }
    }
    ngOnChanges(changes) {
        if (changes.displayMode) {
            this.onDisplayModeChanged(changes.displayMode.previousValue, changes.displayMode.currentValue);
        }
        if (changes.context) {
            this.onProviderChanged(changes.context.previousValue, changes.context.currentValue);
        }
        if (changes.size) {
            this.onSizeChanged(changes.size.previousValue, changes.size.currentValue);
        }
        if (changes.resizeMode) {
            this.onResizeModeChanged(changes.resizeMode.previousValue, changes.resizeMode.currentValue);
        }
    }
    doubleFingerZooming() {
        const scaleElement = this.$svg.find('div.svg-content').first()[0];
        const self = this;
        self.initWidth = scaleElement.offsetWidth;
        self.initHeight = scaleElement.offsetHeight;
        self.lastScale = 1;
        scaleElement.addEventListener('touchstart', function (e) {
            self.pageX = e.targetTouches[0].pageX;
            self.pageY = e.targetTouches[0].pageY;
            self.initX = !lodashIsNaN(parseInt(scaleElement.style.left, 10)) ? parseInt(scaleElement.style.left, 10) : 0;
            self.initY = !lodashIsNaN(parseInt(scaleElement.style.top, 10)) ? parseInt(scaleElement.style.top, 10) : 0;
            if (e.touches.length >= 2) {
                self.startTouch = e.touches;
            }
            self.isTouch = true;
        }, false);
        scaleElement.addEventListener('touchmove', function (e) {
            if (e.touches.length === 1 && self.isTouch && self.lastScale > 1) {
                e.preventDefault();
                const touchMoveX = e.targetTouches[0].pageX, touchMoveY = e.targetTouches[0].pageY;
                const left = Number(touchMoveX) - Number(self.pageX) + Number(self.initX);
                const top = Number(touchMoveY) - Number(self.pageY) + Number(self.initY);
                if (left > -(self.lastScale - 1) * self.initWidth / 2 && left < (self.lastScale - 1) * self.initWidth / 2) {
                    scaleElement.style.left = left + 'px';
                }
                if (top > -(self.lastScale - 1) * self.initHeight / 2 && top < (self.lastScale - 1) * self.initHeight / 2) {
                    scaleElement.style.top = top + 'px';
                }
            }
            if (e.touches.length >= 2 && self.isTouch) {
                e.preventDefault();
                const now = e.touches;
                const scale = (self.getDistance(now[0], now[1]) / self.getDistance(self.startTouch[0], self.startTouch[1]));
                let nowScale = self.lastScale;
                if (scale >= 1) {
                    nowScale *= 1.008;
                }
                if (nowScale < 1) {
                    nowScale = 1;
                }
                if (nowScale > 5) {
                    nowScale = 5;
                }
                if (scale < 1) {
                    nowScale *= 0.992;
                    scaleElement.style.left = -(nowScale - 1) * self.initWidth / 8 + 'px';
                    scaleElement.style.top = -(nowScale - 1) * self.initHeight / 8 + 'px';
                }
                scaleElement.style.transform = 'scale(' + nowScale + ')';
                self.lastScale = nowScale;
            }
        }, false);
        scaleElement.addEventListener('touchend', function () {
            if (self.isTouch) {
                self.isTouch = false;
            }
        }, false);
    }
    getDistance(p1, p2) {
        const x = p2.pageX - p1.pageX, y = p2.pageY - p1.pageY;
        return Math.sqrt((x * x) + (y * y));
    }
    ngOnDestroy() {
        if (this.host) {
            this.host.dispose();
        }
    }
    onProviderChanged(oldValue, newValue) {
        if (isEqual(oldValue, newValue)) {
            return;
        }
        if (this.host) {
            this.host.dispose();
            this.host = null;
        }
        if (newValue) {
            this.$svg = $(this.el.nativeElement).find('div.svgView').first();
            this.$svg.empty();
            const svgRootClass = 'S' + Guid.newGuid().toString('n');
            this.hostContainerId = 'H' + Guid.newGuid().toString('n');
            this.$svg.addClass(svgRootClass);
            const guiOptions = {
                svgRootClass: svgRootClass,
                hostContainerId: this.hostContainerId,
                el: this.el
            };
            const host = new GuiHost(this.injector, this.bsModalService, newValue, guiOptions, this.el);
            /*
             * if configureViewCode exist then load by configureViewCode else load by configureViewId
             */
            (this.context.configureViewCode ? host.loadByConfigureViewCode(this.context.configureViewCode) :
                host.load(this.context.configureViewId)).then(t => {
                // 加载结束后，如果context发生了变化，直接返回。
                if (!isEqual(this.context, t.context)) {
                    t.dispose();
                    return;
                }
                this.host = host;
                this.host.resizeView(this.size, this.viewResizeMode);
                this.$svg.append(t.element);
                if (this.isMobileMode) {
                    this.doubleFingerZooming();
                }
                this.loaded.emit();
            }).catch(error => {
                this.$svg.append(`<p>${this.localization.loadFailed}</p>`);
                this.loadFailed.emit(error);
            });
        }
        else {
            if (this.$svg) {
                this.$svg.empty();
            }
            this.host = null;
        }
    }
    onSizeChanged(oldValue, newValue) {
        if (!this.host || isEqual(oldValue, newValue)) {
            return;
        }
        this.host.updateViewSize(newValue);
        if (this.isMobileMode) {
            this.doubleFingerZooming();
        }
    }
    onResizeModeChanged(oldValue, newValue) {
        if (!this.host || isEqual(oldValue, newValue)) {
            return;
        }
        this.host.updateViewResizeMode(this.viewResizeMode);
    }
    onDisplayModeChanged(oldValue, newValue) {
        if (isEqual(oldValue, newValue)) {
            return;
        }
        this.isMobileMode = this.displayMode === 'Mobile';
        this.globalSettings.displayMode = this.isMobileMode ? DisplayMode.Mobile : DisplayMode.Web;
    }
    refreshCurrentPage() {
        if (this.host.currentViewIndex === undefined) {
            return false;
        }
        const toggleView = this.viewService.toggleViews.get(this.el);
        if (!toggleView) {
            return false;
        }
        toggleView(this.host.currentViewIndex, this.hostContainerId, this.el).subscribe();
        return true;
    }
};
__decorate([
    Input(),
    __metadata("design:type", Object)
], GuiComponent.prototype, "context", void 0);
__decorate([
    Input(),
    __metadata("design:type", Size)
], GuiComponent.prototype, "size", void 0);
__decorate([
    Input(),
    __metadata("design:type", String)
], GuiComponent.prototype, "resizeMode", void 0);
__decorate([
    Input(),
    __metadata("design:type", String)
], GuiComponent.prototype, "displayMode", void 0);
__decorate([
    Output(),
    __metadata("design:type", EventEmitter)
], GuiComponent.prototype, "loadFailed", void 0);
__decorate([
    Output(),
    __metadata("design:type", EventEmitter)
], GuiComponent.prototype, "loaded", void 0);
GuiComponent = __decorate([
    Component({
        selector: 'fc-gui',
        template: "<div> <div class='svgView' style=\"position: relative;display: flex;justify-content: center;align-items: center;\"></div> </div> "
    }),
    __param(1, Inject(LOCALIZATION)),
    __metadata("design:paramtypes", [ElementRef, Object, Injector,
        BsModalService])
], GuiComponent);
export { GuiComponent };
