"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = exports.Kui = void 0;
var _debug = _interopRequireDefault(require("debug"));
var _react = _interopRequireDefault(require("react"));
var _i18n = require("@kui-shell/core/mdist/api/i18n");
var _Capabilities = require("@kui-shell/core/mdist/api/Capabilities");
var _Events = require("@kui-shell/core/mdist/api/Events");
var _Exec = require("@kui-shell/core/mdist/api/Exec");
var _Themes = require("@kui-shell/core/mdist/api/Themes");
var _Client = require("@kui-shell/core/mdist/api/Client");
var _mount = _interopRequireDefault(require("../../mount"));
var _context = _interopRequireDefault(require("./context"));
var _TabContainer = _interopRequireDefault(require("./TabContainer"));
var _UserSettings = _interopRequireWildcard(require("./UserSettings"));
var _StatusStripe = _interopRequireDefault(require("./StatusStripe"));
var _Alert = _interopRequireDefault(require("../spi/Alert"));
var _Loading = _interopRequireDefault(require("../spi/Loading"));
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/*
 * 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.
 */
var __awaiter = void 0 && (void 0).__awaiter || function (thisArg, _arguments, P, generator) {
  function adopt(value) {
    return value instanceof P ? value : new P(function (resolve) {
      resolve(value);
    });
  }
  return new (P || (P = Promise))(function (resolve, reject) {
    function fulfilled(value) {
      try {
        step(generator.next(value));
      } catch (e) {
        reject(e);
      }
    }
    function rejected(value) {
      try {
        step(generator["throw"](value));
      } catch (e) {
        reject(e);
      }
    }
    function step(result) {
      result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
    }
    step((generator = generator.apply(thisArg, _arguments || [])).next());
  });
};
// FIXME:
/* eslint-disable react/prop-types */

const InputStripe = _react.default.lazy(() => Promise.resolve().then(() => require('./InputStripe')));
const LoadingCard = _react.default.lazy(() => Promise.resolve().then(() => require('./LoadingCard')));
const debug = (0, _debug.default)('<Kui/>');
const strings = (0, _i18n.i18n)('client');
const Popup = _react.default.lazy(() => Promise.resolve().then(() => require('./Popup')));
/**
 * Here we arrange the CSS for base functionality of Kui. Order is
 * preserved in the resulting <link> tags.
 *
 */

const defaultThemeProperties = {
  components: 'patternfly',
  topTabNames: 'fixed'
};
/**
 * Render the main body of our client.
 *
 * |Notes on Session Initialization|: to provide custom views for
 * session initialization (only relevant for browser-based hosted
 * Kui), you can instantiate <Kui/> with these properties (defined in
 * KuiConfiguration), show here with some sample views:
 *
 * <Kui
 *    loading={<div className="kui--hero-text">Hold on...</div>}
 *    reinit={<div className="kui--hero-text">Connection broken...</div>}
 *    loadingError={err => <div className="kui--hero-text">{err.toString()}</div>}
 *    loadingDone={<div>Welcome to Kui</div>}
 * />
 *
 */
class Kui extends _react.default.PureComponent {
  constructor(props) {
    super(props);
    this.firstTab = true;
    this._onTabReady = this.onTabReady.bind(this);
    let {
      commandLine
    } = this.props;
    // If props did not specify a commandLine, perhaps the client
    // wishes us to auto-play a guidebook?
    if (!commandLine && (0, _Client.singletonGuidebooks)() && (0, _Client.showGuidebooksSidebar)()) {
      const autoplay = (0, _Client.firstOpenGuidebook)();
      if (autoplay) {
        commandLine = ['replay', '-r', autoplay];
      }
    }
    let quietExecCommand = this.props.quietExecCommand !== undefined ? this.props.quietExecCommand : !this.props.isPopup;
    if ((0, _Capabilities.inBrowser)()) {
      const windowQuery = window.location.search;
      if (windowQuery) {
        // parse and extract the question mark in window.location.search
        // e.g. query = { command: 'replay /kui/welcome.json' }
        const query = require('querystring').parse(windowQuery.substring(1));
        // To avoid SQL injection attacks, users can only query with `replay` command
        if (query.command && /^replay/.test(query.command)) {
          commandLine = query.command.split(' ');
          quietExecCommand = false;
        }
      }
    }
    try {
      const userOverrides = (0, _UserSettings.default)();
      this.state = Object.assign({}, this.defaultSessionBehavior(), this.defaultFeatureFlag(), props, userOverrides, {
        userOverrides,
        isBootstrapped: !!props.noBootstrap,
        commandLine,
        quietExecCommand
      });
      debug('initial state:inBrowser?', (0, _Capabilities.inBrowser)());
      debug('initial state:given properties', props);
      debug('initial state:final value', this.state);
    } catch (err) {
      console.log('using default configuration');
      this.state = {
        isBootstrapped: !!props.noBootstrap,
        commandLine,
        quietExecCommand
      };
    }
  }
  componentDidMount() {
    return __awaiter(this, void 0, void 0, function* () {
      const themeP = yield (0, _Themes.findThemeByName)((yield (0, _Themes.getPersistedThemeChoice)()) || (yield (0, _Themes.getDefaultTheme)()));
      /* if (!this.props.noBootstrap) {
        await import('@kui-shell/core')
          .then(_ => _.bootIntoSandbox())
          .then(() => {
            this.setState({ isBootstrapped: true })
          })
      } */
      // refresh the UI after user changes settings overrides
      (0, _UserSettings.on)(evt => {
        this.setState(curState => {
          // a bit of care is needed to handle removing keys
          if (evt !== 'set') {
            for (const key in curState.userOverrides) {
              delete curState[key];
            }
          }
          const newUserOverrides = (0, _UserSettings.default)();
          return Object.assign(newUserOverrides, {
            userOverrides: newUserOverrides
          });
        });
      });
      const {
        theme
      } = yield themeP;
      _Events.eventChannelUnsafe.on('/theme/change', this.onThemeChange.bind(this));
      this.setState(curState => {
        const stateWithThemeProps = Object.assign({}, theme, curState);
        debug('state with theme props', theme, curState);
        return stateWithThemeProps;
      });
    });
  }
  defaultFeatureFlag() {
    return {
      sidecarName: 'breadcrumb',
      showWelcomeMax: -1
    };
  }
  /** Mount any guidebooks referenced by the `@kui-shell/client/config.d/notebooks.json` model */
  static mountGuidebooks() {
    // FIXME: require versus import; fixing this will require some
    // refactoring of the plugin-core-support logic
    const {
      notebookVFS
    } = require('@kui-shell/plugin-core-support');
    // notebooks hosted by plugin-client-common; we need to defer this
    // a bit, to help with bootstrapping issues
    debug('Mounting plugin-client-common guidebooks', _mount.default);
    notebookVFS.cp(undefined, _mount.default, '/kui');
    const guidebooks = (0, _Client.clientGuidebooks)();
    if (guidebooks && Array.isArray(guidebooks)) {
      debug('Mounting client guidebooks', guidebooks);
      notebookVFS.mkdir({
        argvNoOptions: ['mkdir', '/kui/client']
      });
      notebookVFS.cp(undefined, guidebooks.map(filename => `plugin://client/notebooks/${filename}`), '/kui/client');
    }
  }
  defaultLoading() {
    return _react.default.createElement(_Loading.default, {
      className: "somewhat-larger-text",
      description: strings('Please wait while we connect to your cluster')
    });
  }
  defaultReinit() {
    return _react.default.createElement(_Alert.default, {
      hideCloseButton: true,
      className: "kui--terminal-alert kui--connection-lost top-pad left-pad right-pad",
      alert: {
        type: 'error',
        title: strings('Lost connection to your cluster'),
        body: strings('Attempting to reconnect...')
      }
    });
  }
  defaultLoadingDone() {
    return (0, _Client.isOffline)() ? null : repl => !(0, _Capabilities.inBrowser)() ? undefined : _react.default.createElement(LoadingCard, {
      repl: repl
    });
  }
  defaultLoadingError() {
    return function defaultLoadingError(err) {
      return _react.default.createElement(_Alert.default, {
        className: "top-pad",
        alert: {
          type: 'error',
          title: strings('Error connecting to your cluster'),
          body: err.toString()
        }
      });
    };
  }
  /**
   * For browser-based clients, this defines the default UI for
   * session initialization.
   *
   */
  defaultSessionBehavior() {
    const behavior = !(0, _Capabilities.inBrowser)() ? {} : {
      loading: this.defaultLoading(),
      reinit: this.defaultReinit(),
      loadingError: this.defaultLoadingError(),
      loadingDone: this.defaultLoadingDone()
    };
    debug('defaultSessionBehavior', behavior);
    return behavior;
  }
  onThemeChange({
    themeModel
  }) {
    this.setState(curState => {
      // note the priority order, from highest to lowest:
      //  1) any properties defined by the theme (since we just switched themes)
      //  2) any properties defined by the container of this <Kui/>
      //  3) default choices
      //  4) any prior state
      // re: ordering of 3 and 4, see https://github.com/IBM/kui/issues/4423
      const stateAfterThemeChange = Object.assign({}, curState, defaultThemeProperties, this.props, themeModel);
      debug('state after theme change', stateAfterThemeChange);
      return stateAfterThemeChange;
    });
  }
  /**
   * Props to pass to StatusStripe. This allows us to set the desired
   * status stripe color at startup time, rather than seeing the
   * default color, followed quickly by a change to the color desired
   * by the controller backing the given `props.commandLine`. The
   * controller may still want to specialize the status stripe
   * further, but at least we can avoid that odd
   * e.g. defaultColor-then-blue effect.
   *
   */
  statusStripeProps() {
    if (this.state.commandLine) {
      const statusStripeIdx = this.state.commandLine.findIndex(_ => _ === '--status-stripe');
      if (statusStripeIdx >= 0) {
        return {
          type: this.props.commandLine[statusStripeIdx + 1]
        };
      }
    }
  }
  componentDidCatch(error, errorInfo) {
    console.error(error, errorInfo);
  }
  onTabReady(tab) {
    return __awaiter(this, void 0, void 0, function* () {
      if (this.state.commandLine && this.firstTab) {
        this.firstTab = false;
        setTimeout(() => (0, _Exec.pexecInCurrentTab)(this.state.commandLine.map(_ => (0, _Exec.encodeComponent)(_)).join(' '), tab, this.state.quietExecCommand));
      }
    });
  }
  render() {
    if (!this.state.isBootstrapped) {
      return _react.default.createElement(_Loading.default, null);
    }
    if (this.props.isPopup && this.state.commandLine) {
      return _react.default.createElement(_context.default.Provider, {
        value: this.state
      }, _react.default.createElement(_react.default.Suspense, {
        fallback: _react.default.createElement("div", null)
      }, _react.default.createElement(Popup, {
        commandLine: this.state.commandLine,
        noHelp: this.props.noHelp,
        noSettings: this.props.noSettings
      }, this.props.children)));
    } else {
      const bottom = !!this.props.bottomInput && _react.default.createElement(InputStripe, null, this.props.bottomInput);
      return _react.default.createElement(_context.default.Provider, {
        value: this.state
      }, _react.default.createElement(_react.default.Suspense, {
        fallback: _react.default.createElement("div", null)
      }, _react.default.createElement("div", {
        className: "kui--full-height"
      }, _react.default.createElement(_TabContainer.default, {
        productName: this.props.productName,
        version: this.props.version,
        noActiveInput: this.props.noActiveInput || !!this.props.bottomInput || (0, _Client.isOffline)(),
        bottom: bottom,
        noNewTabButton: this.props.noNewTabButton,
        noNewSplitButton: this.props.noNewSplitButton,
        title: this.props.initialTabTitle || ((0, _Client.isOffline)() ? ' ' : undefined),
        onTabReady: this.state.commandLine && this._onTabReady,
        closeableTabs: this.props.closeableTabs,
        noTopTabs: this.props.noTopTabs || (0, _Client.singletonGuidebooks)(),
        guidebooks: this.props.guidebooks === false ? undefined : this.props.guidebooks || (0, _Client.guidebooksMenu)(),
        guidebooksCommand: this.props.guidebooksCommand || ((0, _Client.singletonGuidebooks)() ? 'commentary --replace --readonly -f' : undefined),
        guidebooksExpanded: this.props.guidebooksExpanded || (0, _Client.showGuidebooksSidebar)()
      }), this.props.toplevel, this.props.statusStripe !== false && _react.default.createElement(_StatusStripe.default, Object.assign({
        noHelp: this.props.noHelp,
        noSettings: this.props.noSettings
      }, this.statusStripeProps()), this.props.children))));
    }
  }
}
exports.Kui = Kui;
(() => {
  Kui.mountGuidebooks();
})();
var _default = Kui;
exports.default = _default;