import { LOGGER_SERVICE_TOKEN } from '../logger';
import { ConfigIsEmptyError } from '../shared';
import { ViewService } from '../view/view.service';
import { GuiView } from './gui-view';
import { map } from 'rxjs/operators';
export class GuiHost {
    constructor(injector, bsModalService, context, guiOptions, el) {
        this.injector = injector;
        this.bsModalService = bsModalService;
        this.context = context;
        this.guiOptions = guiOptions;
        this.el = el;
        this.logger = injector.get(LOGGER_SERVICE_TOKEN);
        const toggleViewFunc = (viewIndex, parentContainerId, baseEl) => {
            this.currentViewIndex = viewIndex;
            return this.context.configStore.viewStore.getViewConfig(viewIndex).pipe(map(config => {
                if (this.currentViewIndex !== viewIndex) {
                    return;
                }
                if (!config || !config.config || !config.config.length) {
                    throw new ConfigIsEmptyError();
                }
                if (this.currentView) {
                    this.currentView.dispose();
                }
                this.currentView = new GuiView(this.injector, this.bsModalService, this.context);
                const hostGuiOptions = {
                    svgRootClass: this.guiOptions.svgRootClass,
                    hostContainerId: parentContainerId,
                    el: baseEl
                };
                this.currentView.load(config, hostGuiOptions);
                this.currentView.resize(this.currentViewSize, this.currentViewReiszeMode, this.guiOptions.svgRootClass);
                this.containerEl = $(baseEl.nativeElement).find(`div#${parentContainerId}`).first();
                this.containerEl.empty();
                this.containerEl.append(this.currentView.element);
                this.logger.debug(`[GUI] Toggle View(${viewIndex}) successed.`);
            }));
        };
        injector.get(ViewService).toggleViews.set(el, toggleViewFunc);
    }
    get element() {
        if (this.containerEl) {
            return this.containerEl[0];
        }
        else {
            throw new Error('Gui Host not loaded yet.');
        }
    }
    /**
     * Load gui host and main view.
     */
    load(configureViewId) {
        if (this.isLoaded) {
            throw new Error('The GuiHost already loaded.');
        }
        this.isLoaded = true;
        this.containerEl = $(`<div class="svg-content" id= "${this.guiOptions.hostContainerId}" style="display:flex;position:relative;"></div>`);
        const result = new Promise((resolve, reject) => {
            if (configureViewId && configureViewId !== 0) {
                this.loadViewConfigByConfigureViewId(resolve, reject, configureViewId);
            }
            else {
                this.loadMainViewConfig(resolve, reject);
            }
        });
        return result;
    }
    loadByConfigureViewCode(configureViewCode) {
        if (this.isLoaded) {
            throw new Error('The GuiHost already loaded.');
        }
        this.isLoaded = true;
        this.containerEl = $(`<div class="svg-content" id= "${this.guiOptions.hostContainerId}" style="display: inline-block;position: relative;"></div>`);
        const result = new Promise((resolve, reject) => {
            if (configureViewCode) {
                this.loadViewConfigByConfigureViewCode(resolve, reject, configureViewCode);
            }
            else {
                this.loadMainViewConfig(resolve, reject);
            }
        });
        return result;
    }
    loadMainViewConfig(resolve, reject) {
        this.context.configStore.viewStore.getMainViewConfig().subscribe(config => {
            if (config.config && config.config.length) {
                this.currentView = new GuiView(this.injector, this.bsModalService, this.context);
                this.currentView.load(config, this.guiOptions);
                this.containerEl.empty();
                this.containerEl.append(this.currentView.element);
                resolve(this);
                this.logger.debug('[GUI] Host loaded.');
            }
            else {
                reject(new ConfigIsEmptyError());
            }
        }, error => {
            this.logger.error('[GUI] Load failed: ' + error.stack);
            reject(error);
        });
    }
    loadViewConfigByConfigureViewId(resolve, reject, configureViewId) {
        this.context.configStore.viewStore.getViewConfigByConfigureViewId(configureViewId).subscribe(config => {
            this.handleViewConfigCallback(resolve, reject, config);
        }, error => {
            this.logger.error('[GUI] Load failed: ' + error.stack);
            reject(error);
        });
    }
    loadViewConfigByConfigureViewCode(resolve, reject, configureViewCode) {
        this.context.configStore.viewStore.getViewConfigByConfigureViewCode(configureViewCode).subscribe(config => {
            this.handleViewConfigCallback(resolve, reject, config);
        }, error => {
            this.logger.error('[GUI] Load failed: ' + error.stack);
            reject(error);
        });
    }
    handleViewConfigCallback(resolve, reject, config) {
        if (!config.config || !config.config.length) {
            reject(new ConfigIsEmptyError());
        }
        this.currentView = new GuiView(this.injector, this.bsModalService, this.context);
        this.currentView.load(config, this.guiOptions);
        this.containerEl.empty();
        this.containerEl.append(this.currentView.element);
        resolve(this);
        this.logger.debug('[GUI] Host loaded.');
    }
    /**
     * Resize current view
     * @param size : target view size
     * @param resizeMode : target resize mode
     */
    resizeView(size, resizeMode) {
        if (this.currentView) {
            this.currentView.resize(size, resizeMode, this.guiOptions.svgRootClass);
            this.currentViewSize = size;
            this.currentViewReiszeMode = resizeMode;
        }
    }
    /**
     * Update current view size;
     * @param size : target view size
     */
    updateViewSize(size) {
        if (!this.currentView) {
            return;
        }
        this.currentView.resize(size, this.currentViewReiszeMode, this.guiOptions.svgRootClass);
        this.currentViewSize = size;
    }
    /**
     * Resize current view
     * @param size : target view size
     * @param resizeMode : target resize mode
     */
    updateViewResizeMode(resizeMode) {
        if (this.currentView) {
            this.currentView.resize(this.currentViewSize, resizeMode, this.guiOptions.svgRootClass);
            this.currentViewReiszeMode = resizeMode;
        }
    }
    dispose() {
        if (this.currentView) {
            this.currentView.dispose();
        }
        if (this.context) {
            this.context.dispose();
        }
        this.logger.debug('[GUI] GuiHost disposed.');
    }
}
