import { __asyncGenerator, __await, __decorate, __metadata } from "tslib";
import '@material/web/icon/icon.js';
import '@material/web/button/elevated-button.js';
import '@material/web/progress/linear-progress.js';
import '@operato/property-editor/ox-properties-dynamic-view.js';
import '@operato/markdown';
import '@operato/board/ox-board-viewer.js';
import './equipment-info';
import gql from 'graphql-tag';
import { css, html, LitElement } from 'lit';
import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
import { customElement, property, query, state } from 'lit/decorators.js';
import { asyncReplace } from 'lit/directives/async-replace.js';
import { client } from '@operato/graphql';
import { i18next } from '@operato/i18n';
import { ScrollbarStyles } from '@operato/styles';
import { sleep } from '@operato/utils';
import { provider } from '@things-factory/board-ui/dist-client';
import { evaluateEquipment } from '../graphql/evaluate-equipment';
import { getAvailableMoleculeList } from './utils';
const ActivityFetchResult = `\
{
  id
  name
  model {
    name
    description
    active
    tag
    inout
    type
    unit
    options
    quantifier
    spec
  }
  thumbnail
  uiType
  uiSource
  reportType
  reportSource
  createdAt
}`;
let EquipmentEvaluator = class EquipmentEvaluator extends LitElement {
    constructor() {
        super(...arguments);
        this.tabName = 'level1';
        this.waitingProgress = false;
    }
    render() {
        const { help } = this.equipment.nature;
        const about = `/helps/${help || 'index'}.md`;
        var tabName = this.tabName ? this.tabName : 'level1';
        return html `
      <div
        tab
        @click=${(e) => {
            this.tabName = e.target.getAttribute('name');
        }}
      >
        <div name="level1" ?selected=${tabName == 'level1'}>
          <md-icon>analytics</md-icon>&nbsp;${i18next.t('label.process-analysis')}
        </div>
        <div name="input" ?selected=${tabName == 'input'}>
          <md-icon>edit_note</md-icon>&nbsp;${i18next.t('label.design-input')}
        </div>
        <div name="result" ?selected=${tabName == 'result'}>
          <md-icon>legend_toggle</md-icon>&nbsp;${i18next.t('label.design-output')}
        </div>
      </div>

      <div content>
        ${{
            level1: html `<equipment-info .equipment=${this.equipment}></equipment-info>`,
            input: html `
            ${this.activityInputContent()}
            <md-elevated-button @click=${() => this.onRequestEvaluation()}>
              <md-icon slot="icon">backup</md-icon>
              ${String(i18next.t('label.request-evaluation'))}
            </md-elevated-button>
          `,
            result: html `
            ${this.activityResultContent()}
            <md-elevated-button @click=${() => this.onReportPDF()}>
              <md-icon slot="icon">download</md-icon>
              PDF Report
            </md-elevated-button>
          `,
            help: html ` <ox-markdown .src=${about} scrollable></ox-markdown>`
        }[this.tabName]}
      </div>
    `;
    }
    firstUpdated() {
        var _a;
        const { type } = (_a = this.equipment) === null || _a === void 0 ? void 0 : _a.state;
        this.fetchActivity(type);
    }
    async fetchActivity(name) {
        const response = await client.query({
            query: gql `
        query activityByName($name: String!) {
          activityByName(name: $name) ${ActivityFetchResult}
        }
      `,
            variables: {
                name
            }
        });
        this.activity = response.data.activityByName;
    }
    async onRequestEvaluation() {
        var _a;
        const { type, refid } = (_a = this.equipment) === null || _a === void 0 ? void 0 : _a.state;
        this.output = this.getOutputFromBoard();
        // TODO: need to confirm the in/out format of equiopment level2
        try {
            this.waitingProgress = true;
            //this.equipmentLv2Result = await evaluateEquipment({
            const evaluateResult = await evaluateEquipment({
                processId: this.processId,
                equipmentId: `${refid}`,
                type,
                params: this.output
            });
            this.equipmentLv2Result = evaluateResult;
        }
        catch (err) {
            console.error(err);
        }
        finally {
            this.waitingProgress = false;
            this.tabName = this.equipmentLv2Result ? 'result' : this.tabName;
        }
    }
    async onReportPDF() {
        var _a, _b, _c, _d, _e, _f;
        const { type: equipmentType, inlets = [], outlets = [], anchors, state: equipmentState = {}, nature: equipmentNature = {}, data: equipmentData = {} } = this.equipment;
        // fetch the level2 boards info of this equipment type
        const streams = [
            ...inlets.map(stream => {
                const { refid, streamType: type } = (stream === null || stream === void 0 ? void 0 : stream.state) || {};
                const { data = {}, to } = stream;
                return Object.assign({ refid,
                    type, anchor: to.anchor, inout: 'in' }, data);
            }),
            ...outlets.map(stream => {
                const { refid, streamType: type } = (stream === null || stream === void 0 ? void 0 : stream.state) || {};
                const { data = {}, from } = stream;
                return Object.assign({ refid,
                    type, anchor: from.anchor, inout: 'out' }, data);
            })
        ];
        anchors.forEach(anchor => {
            if (!streams.find(stream => stream.anchor == anchor.name)) {
                streams.push({ anchor: anchor.name, type: anchor.type, inout: anchor.inout });
            }
        });
        var massFractions = [];
        var moleFractions = [];
        getAvailableMoleculeList().forEach(material => {
            massFractions.push(streams.map(stream => (stream.type === 'fluid' && stream.Y && material in stream.Y ? stream.Y[material] : null)));
            moleFractions.push(streams.map(stream => (stream.type === 'fluid' && stream.X && material in stream.X ? stream.X[material] : null)));
        });
        //
        let properties = (equipmentNature === null || equipmentNature === void 0 ? void 0 : equipmentNature.properties) || [];
        properties.forEach(property => {
            property['title'] = i18next.t(`label.${property.label}`);
        });
        const input = this.output;
        const result = this.equipmentLv2Result;
        const reportInfo = {
            name: ((_a = this.activity) === null || _a === void 0 ? void 0 : _a.name) ? i18next.t(`component.${(_b = this.activity) === null || _b === void 0 ? void 0 : _b.name}`) : '',
            input: ((_c = this.activity) === null || _c === void 0 ? void 0 : _c.uiType) === 'board' ? (_d = this.activity) === null || _d === void 0 ? void 0 : _d.uiSource : '',
            output: ((_e = this.activity) === null || _e === void 0 ? void 0 : _e.reportType) === 'board' ? (_f = this.activity) === null || _f === void 0 ? void 0 : _f.reportSource : ''
        };
        const inputs = {
            processId: this.processId,
            reportInfo,
            equipmentData,
            equipmentState,
            equipmentNature,
            streams,
            massFractions,
            moleFractions,
            properties,
            input,
            result
        };
        try {
            var response = await client.query({
                query: gql `
          query DownloadLevel2AnalysisReport($inputs: Object!) {
            downloadLevel2AnalysisReport(inputs: $inputs)
          }
        `,
                variables: {
                    inputs
                }
            });
            const downloadUrl = response.data.downloadLevel2AnalysisReport;
            if (downloadUrl) {
                const link = document.createElement('a');
                link.href = downloadUrl;
                link.download = `STED-L2-${(reportInfo === null || reportInfo === void 0 ? void 0 : reportInfo.name) || ''}.pdf`;
                link.click();
            }
            else {
                console.error('Failed to retrieve the download URL');
            }
        }
        catch (error) {
            console.error('Error while downloading the report:', error);
        }
    }
    activityInputContent() {
        const { uiType = 'generated' } = this.activity || {};
        switch (uiType) {
            case 'template':
                return this.templateContent();
            case 'generated':
                return this.generatedInputContent();
            case 'board':
                return this.boardInputContent();
            case 'page':
            case 'external':
            default:
                return html ``;
        }
    }
    activityResultContent() {
        const { reportType = 'generated' } = this.activity || {};
        switch (reportType) {
            case 'template':
                return this.templateContent();
            case 'generated':
                return this.generatedResultContent();
            case 'board':
                return this.boardResultContent();
            case 'page':
            case 'external':
            default:
                return html ``;
        }
    }
    templateContent() {
        const { uiSource: template } = this.activity;
        return unsafeHTML(template);
    }
    getInputSpec() {
        if (this.activity) {
            const model = this.activity.model;
            return (model || [])
                .filter(item => item.inout === 'in' || item.inout === 'inout')
                .map(item => {
                return Object.assign(Object.assign({}, item), { label: item.name });
            });
        }
        else {
            return this.equipment.designInputProperties;
        }
    }
    getOutputSpec() {
        var _a;
        const model = (_a = this.activity) === null || _a === void 0 ? void 0 : _a.model;
        return (model || [])
            .filter(item => item.inout === 'inout' || item.inout === 'out')
            .map(item => {
            return Object.assign(Object.assign({}, item), { label: item.name });
        });
    }
    generatedInputContent() {
        var input = this.input;
        const inputSpec = this.getInputSpec();
        return html `
      <ox-properties-dynamic-view data-name="input" .props=${inputSpec} .value=${input}></ox-properties-dynamic-view>
    `;
    }
    generatedResultContent() {
        var input = this.input;
        var output = this.output;
        const inputSpec = this.getInputSpec();
        const outputSpec = this.getOutputSpec();
        if (!output) {
            output = inputSpec
                .filter(item => item.inout === 'inout')
                .reduce((inout, item) => {
                inout[item.name] = input[item.name];
                return inout;
            }, {});
        }
        return html `
      <ox-properties-dynamic-view
        data-name="output"
        .props=${outputSpec}
        .value=${output}
        @property-change=${e => (this.output = e.currentTarget.value)}
      ></ox-properties-dynamic-view>
    `;
    }
    boardInputContent() {
        var input = this.input;
        var output = this.output;
        var equipment = this.equipment;
        const { uiSource: boardId } = this.activity;
        if (!this.board || this.board.id !== boardId) {
            this.board = {
                id: boardId
            };
        }
        const streams = equipment.anchors.reduce((streams, anchor) => {
            var _a;
            const { name, inout } = anchor;
            const line = inout == 'out' ? equipment.findOutletLines(name) : equipment.findInletLines(name);
            streams[name] = (_a = line[0]) === null || _a === void 0 ? void 0 : _a.data;
            return streams;
        }, {});
        var data = Object.assign({ equipment }, streams);
        return html `
      ${this.waitingProgress
            ? html ` <md-linear-progress .progress=${asyncReplace(this.waitProgress())}></md-linear-progress>`
            : html ``}

      <ox-board-viewer
        style="background-color: white;"
        .board=${this.board}
        .provider=${provider}
        .data=${data}
        .values=${Object.assign(Object.assign({}, input), output)}
        hide-fullscreen
        hide-navigation
      ></ox-board-viewer>
    `;
    }
    boardResultContent() {
        var result = this.equipmentLv2Result;
        const { reportSource: boardId } = this.activity;
        if (!this.board || this.board.id !== boardId) {
            this.board = {
                id: boardId
            };
        }
        const streams = this.equipment.anchors.reduce((streams, anchor) => {
            var _a;
            const { name, inout } = anchor;
            const line = inout == 'out' ? this.equipment.findOutletLines(name) : this.equipment.findInletLines(name);
            streams[name] = (_a = line[0]) === null || _a === void 0 ? void 0 : _a.data;
            return streams;
        }, {});
        return html `
      ${this.waitingProgress
            ? html ` <md-linear-progress .progress=${asyncReplace(this.waitProgress())}></md-linear-progress>`
            : html ``}
      <ox-board-viewer
        style="background-color: white;"
        .board=${this.board}
        .provider=${provider}
        .data=${Object.assign(Object.assign({}, streams), result)}
        hide-fullscreen
        hide-navigation
      ></ox-board-viewer>
    `;
    }
    getOutputFromBoard() {
        const outputSpec = this.getOutputSpec();
        const values = this.oxBoardViewer.getSceneValues();
        return outputSpec.reduce((output, spec) => {
            output[spec.name] = values[spec.name];
            return output;
        }, {});
    }
    close() {
        history.back();
    }
    waitProgress() {
        return __asyncGenerator(this, arguments, function* waitProgress_1() {
            var progress = 0;
            while (this.waitingProgress) {
                yield yield __await(Number((++progress % 11) / 10));
                yield __await(sleep(200));
            }
        });
    }
};
EquipmentEvaluator.styles = [
    ScrollbarStyles,
    css `
      :host {
        display: flex;
        flex-direction: column;
        user-select: none;

        background-color: var(--main-section-background-color);
        min-width: 350px;
      }

      [tab] {
        display: flex;
        background-color: rgba(0, 0, 0, 0.08);
        opacity: 0.85;
      }

      [tab] > div {
        flex: 1;

        display: flex;
        align-items: center;
        justify-content: center;
        border-right: 1px solid rgba(0, 0, 0, 0.1);

        color: var(--property-sidebar-tab-icon-color);
        height: 40px;
      }

      [tab] md-icon {
        pointer-events: none;
      }

      [tab] [selected] {
        background-color: var(--main-section-background-color);
        border-left: 1px solid rgba(255, 255, 255, 0.5);
        border-right: 1px solid rgba(0, 0, 0, 0.2);
        opacity: 1;
        font-weight: bold;
      }

      [content] {
        flex: 1;

        position: relative;
        display: flex;
        flex-direction: column;

        overflow: auto;
      }

      md-elevated-button {
        position: absolute;
        top: 4px;
        right: 6px;
      }

      ox-properties-dynamic-view {
        display: block;
      }

      ox-markdown {
        flex: 1;
      }

      ox-board-viewer {
        flex: 1;
        width: 100%;
      }

      md-linear-progress {
        --md-theme-primary: #0ab2ff;
        --md-linear-progress-active-indicator-color: #efefef;
      }

      @media screen and (max-width: 460px) {
        :host {
          width: 100vw;
        }
      }
    `
];
__decorate([
    property({ type: Object }),
    __metadata("design:type", Object)
], EquipmentEvaluator.prototype, "equipment", void 0);
__decorate([
    property({ type: String }),
    __metadata("design:type", String)
], EquipmentEvaluator.prototype, "processId", void 0);
__decorate([
    state(),
    __metadata("design:type", Object)
], EquipmentEvaluator.prototype, "activity", void 0);
__decorate([
    state(),
    __metadata("design:type", Object)
], EquipmentEvaluator.prototype, "board", void 0);
__decorate([
    state(),
    __metadata("design:type", Object)
], EquipmentEvaluator.prototype, "input", void 0);
__decorate([
    state(),
    __metadata("design:type", Object)
], EquipmentEvaluator.prototype, "output", void 0);
__decorate([
    state(),
    __metadata("design:type", String)
], EquipmentEvaluator.prototype, "tabName", void 0);
__decorate([
    state(),
    __metadata("design:type", Boolean)
], EquipmentEvaluator.prototype, "waitingProgress", void 0);
__decorate([
    state(),
    __metadata("design:type", Object)
], EquipmentEvaluator.prototype, "equipmentLv2Result", void 0);
__decorate([
    query('ox-board-viewer'),
    __metadata("design:type", Object)
], EquipmentEvaluator.prototype, "oxBoardViewer", void 0);
EquipmentEvaluator = __decorate([
    customElement('equipment-evaluator')
], EquipmentEvaluator);
export { EquipmentEvaluator };
//# sourceMappingURL=equipment-evaluator.js.map