/*
 * 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 = (this && this.__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());
    });
};
import { ExecType, flatten, i18n } from '@kui-shell/core';
import { isUsage, doHelp, doExecWithPty, doExecWithStdout, defaultFlags, flags, getLabel, getTransformer, getCommandFromArgs, getContainer, getNamespace, isKubeItems, isKubeItemsOfKind, isPod } from '@kui-shell/plugin-kubectl';
import commandPrefix from '../command-prefix';
const strings = 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 = getCommandFromArgs(args);
        if (isUsage(args)) {
            // special case: get --help/-h
            return doHelp(cmd === 'k' ? 'kubectl' : cmd, args);
        }
        if (args.execOptions.raw) {
            return doExecWithStdout(args, undefined, cmd);
        }
        if (args.execOptions.type === 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 doExecWithStdout(args, undefined, cmd);
                }
            }
            const label = 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 getNamespace(args)} -o yaml`, undefined, undefined, {
                    tab: args.tab
                });
            }
            else {
                return args.REPL.qexec(`${cmd} get pod -l ${label} -n ${yield getNamespace(args)} -o json`, undefined, undefined, { tab: args.tab });
            }
        }
        else {
            return doExecWithPty(args);
        }
    });
}
/** Single-resource response */
function transformSingle(defaultMode, args, response) {
    return __awaiter(this, void 0, void 0, function* () {
        return Object.assign({}, yield 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 = flatten(response.items.map(pod => {
            return pod.spec.containers.map(container => Object.assign({}, container, { name: `${pod.metadata.name}:${container.name}` }));
        }));
        const container = 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 (isKubeItemsOfKind(response, isPod)) {
            return transformMulti(defaultMode, args, response);
        }
        else if (isKubeItems(response)) {
            // otherwise, we have an empty list of items
            const error = new Error(strings('No matching pods'));
            error.code = 404;
            throw error;
        }
        if (isPod(response)) {
            return transformSingle(defaultMode, args, response);
        }
    });
}
const doLogs = getOrPty('logs');
const logsFlags = Object.assign({}, flags(booleans), { viewTransformer: viewTransformer('logs') });
const doExec = getOrPty('exec');
const execFlags = Object.assign({}, defaultFlags, { viewTransformer: viewTransformer('terminal') });
export function registerLogs(registrar, cmd) {
    registrar.listen(`/${commandPrefix}/${cmd}/logs`, doLogs, logsFlags);
}
export function registerExec(registrar, cmd) {
    registrar.listen(`/${commandPrefix}/${cmd}/exec`, doExec, execFlags);
}
export default (registrar) => {
    ;
    ['kubectl', 'k'].forEach(cmd => {
        registerLogs(registrar, cmd);
        registerExec(registrar, cmd);
    });
};
//# sourceMappingURL=logs.js.map