/*
 * Copyright 2020 The Kubernetes Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import React from 'react';
import { isAbortableResponse, isMessageWithUsageModel, isMessageWithCode, i18n, isCommentaryResponse, isMarkdownResponse, isMultiModalResponse, isNavResponse, isReactResponse, isRadioTable, isRandomErrorResponse1, isRandomErrorResponse2, isTable, isMixedResponse, isXtermResponse, isUsageError, Util } from '@kui-shell/core';
const Ansi = React.lazy(() => import('./Ansi'));
const Commentary = React.lazy(() => import('../Commentary'));
import HTMLDom from './HTMLDom'; // !! DO NOT MAKE LAZY. See https://github.com/IBM/kui/issues/6758
const XtermDom = React.lazy(() => import('./XtermDom'));
import renderTable from '../Table';
const Markdown = React.lazy(() => import('../Markdown'));
import { KuiContext } from '../../../';
const RadioTableSpi = React.lazy(() => import('../../spi/RadioTable'));
import { isError } from '../../Views/Terminal/Block/BlockModel';
const TopNavSidecar = React.lazy(() => import('../../Views/Sidecar/TopNavSidecarV2'));
const LeftNavSidecar = React.lazy(() => import('../../Views/Sidecar/LeftNavSidecarV2'));
import { MutabilityContext } from '../../Client/MutabilityContext';
const strings = i18n('plugin-client-common', 'errors');
/**
 * Component that renders a "ScalarResponse", which is a command
 * response that doesn't require any particularly special
 * interpretation or visualization of the inner structure --- i.e. a
 * response that is suitable for rendering directly in the Terminal.
 *
 */
export default class Scalar extends React.PureComponent {
    constructor(props) {
        super(props);
        this._onRender = this.onRender.bind(this);
        this.state = Scalar.getDerivedStateFromProps();
    }
    static getDerivedStateFromProps() {
        return {
            catastrophicError: undefined
        };
    }
    static getDerivedStateFromError(error) {
        return { catastrophicError: error };
    }
    componentDidCatch(error, errorInfo) {
        console.error('catastrophic error in Scalar', error, errorInfo);
    }
    onRender(hasContent = true) {
        if (this.props.onRender) {
            setTimeout(() => this.props.onRender(hasContent === 'undefined' ? undefined : hasContent), 0);
        }
    }
    get repl() {
        return this.props.tab ? this.props.tab.REPL : undefined;
    }
    renderResponse(response) {
        const { tab } = this.props;
        if (typeof response === 'boolean') {
            // !!! intentionally quoted and not false, Output.tsx uses
            // !!! assertHasContent !== undefined
            this.onRender('undefined');
            return React.createElement(React.Fragment, null);
        }
        else if (typeof response === 'number') {
            this.onRender();
            return React.createElement("pre", null, response);
        }
        else if (isUsageError(response)) {
            // hopefully we can do away with this shortly
            this.onRender();
            if (typeof response.raw === 'string') {
                return React.createElement("pre", null, response.raw);
            }
            else if (isMessageWithUsageModel(response.raw) || isMessageWithCode(response.raw)) {
                return React.createElement("pre", null, response.raw.message);
            }
            else {
                return React.createElement(HTMLDom, { content: response.raw });
            }
        }
        else if (isXtermResponse(response)) {
            this.onRender(response.rows && response.rows.length > 0);
            return React.createElement(XtermDom, { response: response });
        }
        else if (Buffer.isBuffer(response) || typeof response === 'string' || isError(response)) {
            const message = isError(response) ? response.message : response.toString();
            // Markdown interprets escapes, so we need to double-escape
            if (message[0] === '\u001b') {
                return React.createElement(Ansi, { onRender: this._onRender }, message);
            }
            else {
                return (React.createElement(Markdown, { tab: tab, extraClassName: "kui--markdown-from-repl", source: message.replace(/\\/g, '\\\\').replace(/\n/g, '\n\n'), onRender: this._onRender }));
            }
        }
        else if (isCommentaryResponse(response)) {
            return (React.createElement("span", { className: "flex-fill flex-layout flex-align-stretch" },
                React.createElement(Commentary, Object.assign({}, response.props, { repl: this.repl, tab: tab, execUUID: this.props.execUUID, onRender: this._onRender, willRemove: this.props.willRemove, willUpdateCommand: this.props.willUpdateCommand, willUpdateResponse: (text) => {
                        response.props.children = text;
                    } }))));
        }
        else if (isRadioTable(response)) {
            this.onRender();
            return (React.createElement(KuiContext.Consumer, null, config => React.createElement(RadioTableSpi, { table: response, title: !config.disableTableTitle, repl: this.repl })));
        }
        else if (isTable(response)) {
            const renderBottomToolbar = true;
            const isLargeTable = response.body.length >= 50;
            const renderGrid = isLargeTable &&
                (response.allowedPresentations === undefined || response.allowedPresentations.indexOf('grid') >= 0);
            return renderTable(tab, this.repl, response, undefined, renderBottomToolbar, renderGrid, this._onRender, this.props.isWidthConstrained);
            // ^^^ Notes: typescript doesn't like this, and i don't know why:
            // "is not assignable to type IntrinsicAttributes..."
            // <PaginatedTable {...props} />
        }
        else if (isMixedResponse(response)) {
            if (response.every(_ => typeof _ === 'string' || typeof _ === 'number' || typeof _ === 'boolean')) {
                return React.createElement("pre", { className: "break-all" },
                    "[",
                    response.toString(),
                    "]");
            }
            return (React.createElement(React.Fragment, null, response.map((part, idx) => (React.createElement(Scalar, Object.assign({}, this.props, { key: idx, response: part }))))));
        }
        else if (isReactResponse(response)) {
            this.onRender();
            return response.react;
        }
        else if (Util.isHTML(response)) {
            // ^^^ intentionally using an "else" so that typescript double
            // checks that we've covered every case of ScalarResponse
            this.onRender();
            return React.createElement(HTMLDom, { content: response });
        }
        else if (isMarkdownResponse(response)) {
            return React.createElement(Markdown, { tab: tab, source: response.content, onRender: this._onRender });
        }
        else if (isRandomErrorResponse1(response)) {
            // maybe this is an error response from some random API?
            return (React.createElement(Markdown, { tab: tab, source: strings(response.message ? 'randomError1WithMessage' : 'randomError1', response.code, response.message), onRender: this._onRender }));
        }
        else if (isRandomErrorResponse2(response)) {
            // maybe this is an error response from some random API?
            return React.createElement(Markdown, { tab: tab, source: strings('randomError2', response.errno), onRender: this._onRender });
        }
        else if (isMultiModalResponse(response)) {
            return (React.createElement(MutabilityContext.Consumer, null, value => (React.createElement(TopNavSidecar, { uuid: tab.uuid, tab: tab, execUUID: this.props.execUUID, active: true, response: response, executable: value.executable, onRender: this.props.onRender, willChangeSize: this.props.willChangeSize, argvNoOptions: this.props.completeEvent ? this.props.completeEvent.argvNoOptions : undefined, parsedOptions: this.props.completeEvent ? this.props.completeEvent.parsedOptions : undefined }))));
        }
        else if (isNavResponse(response)) {
            return (React.createElement(LeftNavSidecar, { uuid: tab.uuid, tab: tab, execUUID: this.props.execUUID, active: true, response: response, onRender: this.props.onRender, willChangeSize: this.props.willChangeSize, argvNoOptions: this.props.completeEvent ? this.props.completeEvent.argvNoOptions : undefined, parsedOptions: this.props.completeEvent ? this.props.completeEvent.parsedOptions : undefined }));
        }
        else if (isAbortableResponse(response)) {
            this.onRender();
            return this.renderResponse(response.response);
        }
        console.error('unexpected response from Scalar:', this.props.response);
        this.onRender();
        return React.createElement("pre", { className: "oops" }, "Internal Error in command execution");
    }
    render() {
        if (this.state.catastrophicError) {
            return React.createElement("div", { className: "oops" }, this.state.catastrophicError.toString());
        }
        try {
            return this.renderResponse(this.props.response);
        }
        catch (err) {
            console.error('catastrophic error rendering Scalar', err);
            return React.createElement("pre", null, err.toString());
        }
    }
}
//# sourceMappingURL=index.js.map