/*
 * Copyright 2020 IBM Corporation
 *
 * 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 * as React from 'react';
import { isPopup, inBrowser, eventChannelUnsafe } from '@kui-shell/core';
import sameCommand from '../util/same';
import TitleBar from './TitleBar';
import CircularBuffer from '../util/CircularBuffer';
import '../../../../web/css/static/sidecar.css';
import '../../../../web/css/static/sidecar-main.css';
import '../../../../web/css/static/sidecar-carbon.css';
/** cwd */
export function cwd() {
    return process.env.PWD || (!inBrowser() && process.cwd());
}
export class BaseSidecar extends React.PureComponent {
    constructor(props) {
        super(props);
        this.cleaners = [];
        // Interpret Escape key as a toggle of the view's width
        const onEscape = this.onEscape.bind(this);
        document.addEventListener('keydown', onEscape);
        this.cleaners.push(() => document.removeEventListener('keydown', onEscape));
        // ^^^ Note! keydown versus keyup is important (for now at
        // least; @starpit 20200408); see https://github.com/IBM/kui/issues/4215
    }
    componentDidCatch(error, errorInfo) {
        console.error(error, errorInfo);
    }
    /** Consult our History model for a match */
    lookupHistory(response, argvNoOptions, parsedOptions, cwd) {
        return this.state.history.findIndex(sameCommand(argvNoOptions, parsedOptions, cwd));
    }
    /** Enter a given `response` into the History model */
    onResponse(event) {
        const { tab, response, execUUID, argvNoOptions, parsedOptions } = event;
        this.setState(curState => {
            const existingIdx = curState.history ? this.lookupHistory(response, argvNoOptions, parsedOptions, cwd()) : -1;
            const current = this.idempotent() && existingIdx !== -1
                ? curState.history.peekAt(existingIdx)
                : this.getState(tab, response, execUUID, argvNoOptions, parsedOptions);
            if (current) {
                this.props.willChangeSize(this.defaultWidth());
                if (!curState.history) {
                    return {
                        tab,
                        repl: tab.REPL,
                        current,
                        history: new CircularBuffer(current, this.capacity())
                    };
                }
                else {
                    if (existingIdx === -1) {
                        curState.history.push(current);
                    }
                    else {
                        curState.history.update(existingIdx, current);
                    }
                    return {
                        tab,
                        repl: tab.REPL,
                        current,
                        history: curState.history
                    };
                }
            }
        });
    }
    /** Capacity of the circular buffer; e.g. if 1, then no history */
    capacity() {
        return 15;
    }
    /** Is getState() idempotent? i.e. Will two command executions that satisfy `sameCommand` always produce the same response? */
    idempotent() {
        return false;
    }
    /** Should we display Back/Forward arrows for history navigation? */
    useArrowNavigation() {
        return true;
    }
    /** We are about to go away; invoke the register cleaners. */
    componentWillUnmount() {
        this.cleaners.forEach(_ => _());
    }
    /** @return the current History entry */
    get current() {
        return this.state.current;
    }
    defaultWidth() {
        return this.props.defaultWidth || "60%" /* Split60 */;
    }
    /** Escape key toggles sidecar visibility */
    onEscape(evt) {
        if (evt.key === 'Escape' &&
            this.props.active &&
            !document.getElementById('confirm-dialog') &&
            !isPopup() &&
            this.current) {
            if (this.props.willChangeSize) {
                this.props.willChangeSize(this.props.width === "0%" /* Closed */ ? this.defaultWidth() : "0%" /* Closed */);
            }
        }
    }
    onMaximize() {
        if (this.props.willChangeSize) {
            this.props.willChangeSize("100%" /* Maximized */);
        }
    }
    onRestore() {
        if (this.props.willChangeSize) {
            this.props.willChangeSize(this.defaultWidth());
        }
    }
    onClose() {
        if (this.props.onClose) {
            this.props.onClose();
        }
        if (this.props.willChangeSize) {
            this.props.willChangeSize("0%" /* Closed */);
        }
    }
    isFixedWidth() {
        return false;
    }
    width() {
        switch (this.props.width) {
            case "100%" /* Maximized */:
                return 'visible maximized';
            default:
                return 'visible';
        }
    }
    onScreenshot() {
        if (this.props.willLoseFocus) {
            this.props.willLoseFocus();
        }
        // async, to allow willLoseFocus() to take affect
        setTimeout(() => {
            eventChannelUnsafe.emit('/screenshot/element', this.state.dom);
        });
    }
    title(props) {
        return (React.createElement(TitleBar, Object.assign({}, props, { repl: this.state.tab.REPL, width: this.props.width, fixedWidth: this.isFixedWidth(), onMaximize: this.onMaximize.bind(this), onRestore: this.onRestore.bind(this), onClose: this.onClose.bind(this), willScreenshot: this.onScreenshot.bind(this), back: this.useArrowNavigation() &&
                this.props.width !== "0%" /* Closed */ &&
                this.state.history.hasBuffer() && {
                enabled: this.state.history.hasBefore(),
                onClick: () => {
                    this.state.history.hasBefore() && this.setState(curState => ({ current: curState.history.before() }));
                }
            }, forward: this.useArrowNavigation() &&
                this.props.width !== "0%" /* Closed */ &&
                this.state.history.hasBuffer() && {
                enabled: this.state.history.hasAfter(),
                onClick: () => {
                    this.state.history.hasAfter() && this.setState(curState => ({ current: curState.history.after() }));
                }
            } })));
    }
}
//# sourceMappingURL=BaseSidecar.js.map