import { __decorate, __metadata } from "tslib";
import './things-scene-components.import';
import '@operato/board/ox-board-viewer.js';
import '@operato/oops';
import gql from 'graphql-tag';
import { css, html } from 'lit';
import { customElement, property, query, state } from 'lit/decorators.js';
import { connect } from 'pwa-helpers/connect-mixin.js';
import { buildLabelPrintCommand } from '@operato/barcode';
import { BoardViewer } from '@operato/board';
import { store, PageView } from '@operato/shell';
import { client, gqlContext, subscribe } from '@operato/graphql';
import { clientSettingStore } from '@operato/shell/object-store.js';
import { provider } from '../board-provider';
const NOOP = () => { };
function parseQuery(query) {
    for (const key in query) {
        if (query.hasOwnProperty(key)) {
            try {
                query[key] = JSON.parse(query[key]);
            }
            catch (error) {
                // do nothing
            }
        }
    }
    return query;
}
let BoardViewerPage = class BoardViewerPage extends connect(store)(PageView) {
    get oopsNote() {
        return {
            icon: 'insert_chart_outlined',
            title: 'EMPTY BOARD',
            description: 'There are no board to be shown'
        };
    }
    get context() {
        return {
            /* can set the page title with the 'title' parameter. */
            title: this.lifecycle.params['title'] ||
                (this._board ? this._board.name : this._showSpinner ? 'Fetching board...' : 'Board Not Found'),
            help: this._help
        };
    }
    render() {
        var oops = !this._showSpinner && !this._board && this.oopsNote;
        return oops
            ? html ` <ox-oops-note icon=${oops.icon} title=${oops.title} description=${oops.description}></ox-oops-note> `
            : html `
          <ox-board-viewer
            .board=${this._board}
            .provider=${provider}
            ?hide-fullscreen=${this._interactive}
            ?hide-navigation=${this._interactive}
            .data=${this.data}
            history
          ></ox-board-viewer>
          <ox-oops-spinner ?show=${this._showSpinner}></ox-oops-spinner>
        `;
    }
    updated(changes) {
        if (changes.has('_boardId')) {
            this.refresh();
        }
    }
    pageUpdated(changes, lifecycle) {
        if (this.active) {
            this._boardId = lifecycle.resourceId;
            this._interactive = lifecycle.params['interactive'] === 'true';
            this._help = lifecycle.params['help'];
            this.data = parseQuery(Object.assign({}, lifecycle.params));
        }
        else {
            /*
             * 비활성화된 페이지에서 render update가 발생하지 않으므로, 강제로 scene을 close 한다.
             * 화면이 inactive 될 때, 굳이 scene을 close하는 이유는,
             * 새로운 board가 선택되어 뷰어가 열릴 때, 기존 보드 잔상이 보이지 않도록 하기위해서이다.
             */
            this.stopSubscribing();
            if (this._boardId) {
                let boardViewer = this.boardViewer;
                boardViewer && boardViewer.closeScene();
            }
            this._boardId = '';
        }
    }
    stateChanged(state) {
        this._baseUrl = state.app.baseUrl;
    }
    async fetch(id) {
        if (!id) {
            return;
        }
        return await client.query({
            query: gql `
        query ($id: String!) {
          response: board(id: $id) {
            id
            name
            model
          }
        }
      `,
            variables: { id },
            context: gqlContext()
        });
    }
    async refresh() {
        var _a;
        if (!this._boardId) {
            this._board = null;
            return;
        }
        try {
            this._showSpinner = true;
            this.updateContext();
            var { data, errors } = (await this.fetch(this._boardId)) || {};
            var board = data === null || data === void 0 ? void 0 : data.response;
            if (!board) {
                this._board = null;
                const message = errors === null || errors === void 0 ? void 0 : errors.map(error => error.message).join('\n');
                throw message || 'board not found';
            }
            this._board = Object.assign(Object.assign({}, board), { model: JSON.parse(board.model) });
        }
        catch (ex) {
            document.dispatchEvent(new CustomEvent('notify', {
                detail: {
                    level: 'error',
                    message: ex,
                    ex
                }
            }));
        }
        finally {
            this._showSpinner = false;
            this.updateContext();
            const { autoRefresh = true } = ((_a = (await clientSettingStore.get('board-view'))) === null || _a === void 0 ? void 0 : _a.value) || {};
            autoRefresh && this.startSubscribingForAutoRefresh();
        }
    }
    async startSubscribingForAutoRefresh() {
        if (!this._board) {
            return;
        }
        await this.stopSubscribing();
        this.subscriptionForAutoRefresh = await subscribe({
            query: gql `
          subscription ($id: String!) {
            board(id: $id) {
              id
            }
          }
        `,
            variables: {
                id: this._board.id
            }
        }, {
            next: async ({ data }) => {
                await this.stopSubscribing();
                if (data) {
                    this.refresh();
                }
            }
        });
    }
    async stopSubscribing() {
        var _a;
        await ((_a = this.subscriptionForAutoRefresh) === null || _a === void 0 ? void 0 : _a.unsubscribe());
        delete this.subscriptionForAutoRefresh;
    }
    async getGrf() {
        var { labelRotation } = this._board.model;
        var { width, height, data } = (await this.boardViewer.getSceneImageData()) || {};
        if (!width || !data) {
            throw 'Cannot get SceneImageData...';
        }
        return buildLabelPrintCommand(data, width, height, labelRotation, false, false);
    }
    async printTrick(image) {
        await this.boardViewer.printTrick(image);
    }
};
BoardViewerPage.styles = [
    css `
      :host {
        display: flex;
        flex-direction: column;

        width: 100%; /* 전체화면보기를 위해서 필요함. */
        height: 100%;

        overflow: hidden;
        position: relative;
      }

      ox-board-viewer {
        flex: 1;
      }

      ox-oops-spinner {
        display: none;
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
      }

      ox-oops-spinner[show] {
        display: block;
      }

      ox-oops-note {
        display: block;
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
      }
    `
];
__decorate([
    property({ type: Object }),
    __metadata("design:type", Object)
], BoardViewerPage.prototype, "_board", void 0);
__decorate([
    property({ type: String }),
    __metadata("design:type", String)
], BoardViewerPage.prototype, "_boardId", void 0);
__decorate([
    property({ type: String }),
    __metadata("design:type", String)
], BoardViewerPage.prototype, "_baseUrl", void 0);
__decorate([
    property({ type: String }),
    __metadata("design:type", String)
], BoardViewerPage.prototype, "_help", void 0);
__decorate([
    property({ type: Boolean }),
    __metadata("design:type", Boolean)
], BoardViewerPage.prototype, "_interactive", void 0);
__decorate([
    property({ type: Boolean }),
    __metadata("design:type", Boolean)
], BoardViewerPage.prototype, "_showSpinner", void 0);
__decorate([
    state(),
    __metadata("design:type", Object)
], BoardViewerPage.prototype, "data", void 0);
__decorate([
    query('ox-board-viewer'),
    __metadata("design:type", BoardViewer)
], BoardViewerPage.prototype, "boardViewer", void 0);
BoardViewerPage = __decorate([
    customElement('board-viewer-page')
], BoardViewerPage);
export { BoardViewerPage };
//# sourceMappingURL=board-viewer-page.js.map