/*
 * Copyright 2019 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 { i18n, isTable } from '@kui-shell/core';
import { Parser, getNamespace, getLabelForArgv, isForAllNamespaces } from '@kui-shell/plugin-kubectl';
import { strip, getSystemOverhead } from './get-node-data';
// import { parseAsTime, parseAsSize } from '../lib/parse'
const strings = i18n('plugin-kubectl', 'view-utilization-table');
/**
 * @return an indicator of whether a given pod name is in a given
 * node, subject to any namespace or label filters in the given args
 *
 */
function getPodsInNode(args, forNode) {
    return __awaiter(this, void 0, void 0, function* () {
        const { content } = yield args.REPL.rexec(`kubectl get pods -o json -n ${yield getNamespace(args)} ${getLabelForArgv(args)}`);
        const empty = {};
        if (content && content.items) {
            return content.items
                .filter(_ => _.spec.nodeName === forNode)
                .map(_ => _.metadata.name) // name versus fqn?
                .reduce((M, fqn) => {
                M[fqn] = true;
                return M;
            }, empty);
        }
        else {
            return empty;
        }
    });
}
function withAllNamespaces(args) {
    const args2 = Object.assign({}, args);
    args2.command = args2.command + ' -A';
    args2.argv = args2.argv.slice(0).concat(['-A']);
    return args2;
}
const lighterText = ['processing-text', 'semi-bold'];
function addRow(forThisNS, key, cpu, mem, css, formatAs = 'share') {
    const row = JSON.parse(JSON.stringify(forThisNS.body[0]));
    row.onclick = false;
    row.rowKey = key;
    row.name = strings(key);
    row.attributes[0].value = formatAs === 'share' ? Parser.formatAsCpu(cpu) : (100 * cpu).toFixed(0) + '%';
    row.attributes[1].value = formatAs === 'share' ? Parser.formatAsBytes(mem) : (100 * mem).toFixed(0) + '%';
    if (css) {
        row.css = css;
        row.attributes[0].css = css.join(' ');
        row.attributes[1].css = css.join(' ');
    }
    forThisNS.body.push(row);
}
function addAllNSRow(args, forThisNS, forAllNS) {
    return __awaiter(this, void 0, void 0, function* () {
        if (forThisNS.body && forThisNS.body.length > 0) {
            const cpuTotal = forThisNS.body.reduce((total, row) => total + Parser.cpuShare(row.attributes[0].value), 0);
            const memTotal = forThisNS.body.reduce((total, row) => total + Parser.memShare(row.attributes[1].value), 0);
            addRow(forThisNS, 'Total', cpuTotal, memTotal);
            if (forAllNS.body && forAllNS.body.length > 0) {
                const thisNS = yield getNamespace(args);
                const otherNS = forAllNS.body.filter(_ => _.name !== thisNS);
                const cpuTotal = otherNS.reduce((total, row) => total + Parser.cpuShare(row.attributes[1].value), 0);
                const memTotal = otherNS.reduce((total, row) => total + Parser.memShare(row.attributes[2].value), 0);
                addRow(forThisNS, 'Other Namespaces', cpuTotal, memTotal, lighterText);
            }
        }
        return forThisNS;
    });
}
/**
 * Command handler for `kubectl top pod` default handler
 *
 */
function getPodDataForAllNodes(args, top) {
    return __awaiter(this, void 0, void 0, function* () {
        if (isForAllNamespaces(args.parsedOptions) || args.parsedOptions.containers) {
            return top(args);
        }
        else {
            const [forThisNS, forAllNS] = yield Promise.all([top(args), top(withAllNamespaces(args))]);
            return addAllNSRow(args, forThisNS, forAllNS);
        }
    });
}
/**
 * Command handler for `kubectl top pod --node <node>`
 *
 */
function getPodDataForOneNode(args, top) {
    return __awaiter(this, void 0, void 0, function* () {
        const forNode = args.parsedOptions.node;
        // strip off the --node <node> option
        strip(args, '--node', 1); // 1 means --node takes 1 arg
        if (isForAllNamespaces(args.parsedOptions) || args.parsedOptions.containers) {
            const [podTable, pods] = yield Promise.all([top(args), getPodsInNode(args, forNode)]);
            if (podTable.body) {
                podTable.body = podTable.body.filter(row => pods[row.name]);
            }
            return podTable;
        }
        else {
            const [podTable, pods, podTableInAllNS] = yield Promise.all([
                top(args),
                getPodsInNode(args, forNode),
                top(withAllNamespaces(args))
            ]);
            if (podTable.body) {
                podTable.body = podTable.body.filter(row => pods[row.name]);
            }
            if (podTableInAllNS.body) {
                podTableInAllNS.body = podTableInAllNS.body.filter(row => pods[row.attributes[0].value]);
            }
            return addAllNSRow(args, podTable, podTableInAllNS);
        }
    });
}
/**
 * Command handler for `kubectl top pod` (overrides built-in functionality)
 *
 */
export function topPod(args, top) {
    return __awaiter(this, void 0, void 0, function* () {
        const overheads = getSystemOverhead(args, args.parsedOptions.node);
        // without a --node <node> filter, we use the underlying `top pod` impl
        const table = !args.parsedOptions.node
            ? yield getPodDataForAllNodes(args, top)
            : yield getPodDataForOneNode(args, top);
        if (!isTable(table)) {
            return table;
        }
        else if (table.body.length === 0) {
            throw new Error(strings('No pods found'));
        }
        const ns = yield getNamespace(args);
        table.body.forEach(row => {
            // don't need to filter by node: ${args.parsedOptions.node ? `--node ${args.REPL.encodeComponent(args.parsedOptions.node)}` : ''}
            if (row.onclick) {
                row.onclick = `kubectl top container ${args.REPL.encodeComponent(row.name)} -n ${ns} ${getLabelForArgv(args)}`;
                row.onclickSilence = false;
            }
        });
        const { cpuOverhead, memOverhead /* , cpuCapacity, memCapacity */ } = yield overheads;
        addRow(table, 'System Overheads', cpuOverhead, memOverhead, lighterText);
        const totalRow = table.body.find(_ => _.rowKey === 'Total');
        const otherNSRow = table.body.find(_ => _.rowKey === 'Other Namespaces');
        if (totalRow && otherNSRow) {
            const totalCPU = Parser.cpuShare(totalRow.attributes[0].value) + Parser.cpuShare(otherNSRow.attributes[0].value) + cpuOverhead;
            const totalMem = Parser.memShare(totalRow.attributes[1].value) + Parser.memShare(otherNSRow.attributes[1].value) + memOverhead;
            // addRow(table, strings('Free Capacity'), 1 - totalCPU / cpuCapacity, 1 - totalMem / memCapacity, lighterText, 'percent')
            addRow(table, strings('Overall Total'), totalCPU, totalMem, lighterText);
        }
        return table;
    });
}
/**
 * Command handler for `kubectl top container`
 *
 */
export function topContainer(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const cmd = args.command.replace('top container', 'top pod').replace(/(-A|--all-namespaces)/, '') + ' --containers';
        const allContainers = yield args.REPL.qexec(cmd);
        // filter for the given pod name
        const pod = args.argvNoOptions[args.argvNoOptions.indexOf('container') + 1];
        if (allContainers.body) {
            allContainers.body = allContainers.body.filter(_ => _.name === pod);
            allContainers.body.forEach(row => {
                row.onclick = `kubectl get pod ${args.REPL.encodeComponent(row.name)} -o yaml`;
            });
        }
        return allContainers;
    });
}
//# sourceMappingURL=get-pod-data.js.map