"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.registerLogs = registerLogs;
exports.registerExec = registerExec;
exports.default = void 0;

var _core = require("@kui-shell/core");

var _pluginKubectl = require("@kui-shell/plugin-kubectl");

var _commandPrefix = _interopRequireDefault(require("../command-prefix"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/*
 * Copyright 2019-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.
 */
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());
  });
};

const strings = (0, _core.i18n)('plugin-kubectl', 'logs');
/** for command registration, which of those options is a boolean? */

const booleans = ['p', 'previous', 'f', 'follow'];
/**
 * Send the request to a PTY for deeper handling, then (possibly) add
 * some ANSI control codes for coloring.
 *
 */

function getOrPty(verb) {
  return args => __awaiter(this, void 0, void 0, function* () {
    const cmd = (0, _pluginKubectl.getCommandFromArgs)(args);

    if ((0, _pluginKubectl.isUsage)(args)) {
      // special case: get --help/-h
      return (0, _pluginKubectl.doHelp)(cmd === 'k' ? 'kubectl' : cmd, args);
    }

    if (args.execOptions.raw) {
      return (0, _pluginKubectl.doExecWithStdout)(args, undefined, cmd);
    }

    if (args.execOptions.type === _core.ExecType.TopLevel) {
      if (verb === 'exec') {
        // special case for kubectl exec cat, ls, pwd, etc.
        const idx = args.argvNoOptions.indexOf('exec');
        const execThis = args.argvNoOptions[idx + 2];

        if (execThis === 'cat' || execThis === 'ls' || execThis === 'pwd' || execThis === 'mv' || execThis === 'cp' || execThis === 'ln') {
          return (0, _pluginKubectl.doExecWithStdout)(args, undefined, cmd);
        }
      }

      const label = (0, _pluginKubectl.getLabel)(args);

      if (!label) {
        const idx = args.argvNoOptions.indexOf(verb);
        const name = args.argvNoOptions[idx + 1];
        return args.REPL.qexec(`${cmd} get pod ${name} -n ${yield (0, _pluginKubectl.getNamespace)(args)} -o yaml`, undefined, undefined, {
          tab: args.tab
        });
      } else {
        return args.REPL.qexec(`${cmd} get pod -l ${label} -n ${yield (0, _pluginKubectl.getNamespace)(args)} -o json`, undefined, undefined, {
          tab: args.tab
        });
      }
    } else {
      return (0, _pluginKubectl.doExecWithPty)(args);
    }
  });
}
/** Single-resource response */


function transformSingle(defaultMode, args, response) {
  return __awaiter(this, void 0, void 0, function* () {
    return Object.assign({}, yield (0, _pluginKubectl.getTransformer)(args, response), {
      defaultMode,
      argsForMode: args
    });
  });
}
/** Multiple-resource response. We've already assured that we have >= 1 item via isKubeItemsOfKind(). */


function transformMulti(defaultMode, args, response) {
  return __awaiter(this, void 0, void 0, function* () {
    const containers = (0, _core.flatten)(response.items.map(pod => {
      return pod.spec.containers.map(container => Object.assign({}, container, {
        name: `${pod.metadata.name}:${container.name}`
      }));
    }));
    const container = (0, _pluginKubectl.getContainer)(args, 'logs');
    const owningPod = container && response.items.find(pod => pod.spec.containers.find(_ => _.name === container));
    const owningPodName = owningPod ? owningPod.metadata.name : undefined;
    response.items[0].isSimulacrum = true;
    response.items[0].spec.containers = containers;
    const names = response.items.map(_ => _.metadata.name).join(', ');
    response.items[0].metadata.name = names;
    const multi = yield transformSingle(defaultMode, args, response.items[0]);

    if (owningPodName) {
      const encoded = `${owningPodName}:${container}`;
      multi.argsForMode.parsedOptions.c = multi.argsForMode.parsedOptions.container = encoded;
    } else if (container) {
      // couldn't find a pod for the given container
      const error = new Error('Specified container not found');
      error.code = 404;
      throw error;
    }

    return multi;
  });
}
/** Pod -> MultiModalResponse view transformer */


function viewTransformer(defaultMode) {
  return (args, response) => __awaiter(this, void 0, void 0, function* () {
    if ((0, _pluginKubectl.isKubeItemsOfKind)(response, _pluginKubectl.isPod)) {
      return transformMulti(defaultMode, args, response);
    } else if ((0, _pluginKubectl.isKubeItems)(response)) {
      // otherwise, we have an empty list of items
      const error = new Error(strings('No matching pods'));
      error.code = 404;
      throw error;
    }

    if ((0, _pluginKubectl.isPod)(response)) {
      return transformSingle(defaultMode, args, response);
    }
  });
}

const doLogs = getOrPty('logs');
const logsFlags = Object.assign({}, (0, _pluginKubectl.flags)(booleans), {
  viewTransformer: viewTransformer('logs')
});
const doExec = getOrPty('exec');
const execFlags = Object.assign({}, _pluginKubectl.defaultFlags, {
  viewTransformer: viewTransformer('terminal')
});

function registerLogs(registrar, cmd) {
  registrar.listen(`/${_commandPrefix.default}/${cmd}/logs`, doLogs, logsFlags);
}

function registerExec(registrar, cmd) {
  registrar.listen(`/${_commandPrefix.default}/${cmd}/exec`, doExec, execFlags);
}

var _default = registrar => {
  ;
  ['kubectl', 'k'].forEach(cmd => {
    registerLogs(registrar, cmd);
    registerExec(registrar, cmd);
  });
};

exports.default = _default;