/*
 * Copyright (c) 2013-2017 Red Hat.
 * 
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * Lookup up the metrics named on stdin and generate pmDesc descriptors.
 */

#include <pcp/pmapi.h>
#include <pcp/pmda.h>

int python = 0;

static char *semStr[] = { "0", "PM_SEM_COUNTER", "2", "PM_SEM_INSTANT", "PM_SEM_DISCRETE" };

static char *
indomStr(int indom)
{
    static char buf[32];
    
    if (indom == PM_INDOM_NULL) {
	if (python)
	    strcpy(buf, "c_api.PM_INDOM_NULL");
	else
	    strcpy(buf, "PM_INDOM_NULL");
    }
    else
	if (python)
	    pmsprintf(buf, sizeof(buf), "PMDA.indom(%d)", pmInDom_serial(indom));
	else
	    pmsprintf(buf, sizeof(buf), "0x%04x", indom);

    return buf;
}

int
main(int argc, char *argv[])
{
    int ctx;
    int sts;
    char buf[1024];
    const char *name = buf;
    char *p;
    pmID pmid;
    pmDesc desc;

    if (argc > 1 && strncmp(argv[1], "-p", 2) == 0)
    	python++;

    if (isatty(fileno(stdin))) {
    	fprintf(stderr,
	    "Usage: pminfo metric ... | pmdesc [-p]\n\n"
	    "-p python mode (else C declarations are produced).\n\n"
	    "Reads metric names on stdin and prints a descriptor for each in a table.\n"
	    "The metric descriptor table should be defined in \"./metrics.h\" as follows :\n"
	    "    typedef struct {\n"
	    "        char *name;\n"
            "        pmDesc desc;\n"
            "    } metric_t;\n"
	    "\n"
	    "    extern metric_t metrics[];\n");
	exit(1);
    }

    ctx = pmNewContext(PM_CONTEXT_HOST, "local:");
    if (ctx < 0) {
    	fprintf(stderr, "Error: pmNewContext %s\n", pmErrStr(ctx));
	exit(1);
    }

    if (python) {
	printf(
	    "from pcp.pmapi import pmUnits\n"
	    "from pcp.pmda import PMDA, pmdaMetric, pmdaIndom\n"
	    "import cpmapi as c_api\n"
	    "import os\n"
	    "import re\n"
	    "import sys\n"
	    "\n"
	    "# dict of metrics, indexed by pmid\n"
	    "METRIC_NAME = 0\nMETRIC_TABLE = 1\nMETRIC_COLUMN = 2\nMETRIC_PMDAMETRIC = 3\n"
	    "metrictable = {\n"
	);

    } else {
	printf("/* This file is automatically generated .. do not edit! */\n");
	printf("#include \"metrics.h\"\n\n");
	printf("metric_t metrics[] = {\n");
    }

    while (fgets(buf, sizeof(buf), stdin)) {
	if ((p = strrchr(buf, '\n')) != NULL)
	    *p = '\0';

	if ((sts = pmLookupName(1, &name, &pmid)) < 0) {
	    fprintf(stderr, "Error: pmLookupName \"%s\": %s\n", name, pmErrStr(sts));
	    exit(1);
	}

	if ((sts = pmLookupDesc(pmid, &desc)) < 0) {
	    fprintf(stderr, "Error: pmLookupDesc \"%s\": %s\n", name, pmErrStr(sts));
	    exit(1);
	}

	if (python) {
	    printf("    PMDA.pmid(%d,%d) : ['%s', 'TABLE', 'COLUMN', pmdaMetric(\n"
		   "        PMDA.pmid(%d,%d), c_api.PM_TYPE_%s, %s, c_api.%s, pmUnits(%d,%d,%d,%d,%d,%d))],\n",
		pmID_cluster(pmid), pmID_item(pmid), name,
	    	pmID_cluster(pmid), pmID_item(pmid), pmTypeStr(desc.type),
		indomStr(desc.indom), semStr[desc.sem], desc.units.dimSpace,
		desc.units.dimTime, desc.units.dimCount, desc.units.scaleSpace,
		desc.units.scaleTime, desc.units.scaleCount);

	}
	else {
	    printf("    /* %-8s */ { \"%s\", { 0x%04x, PM_TYPE_%s, %s, %s,\n"
		   "                  { .dimSpace=%d, .dimTime=%d, .dimCount=%d, "
		   ".scaleSpace=%d, .scaleTime=%d, .scaleCount=%d } } },\n",
		pmIDStr(desc.pmid), name, desc.pmid, pmTypeStr(desc.type),
		indomStr(desc.indom), semStr[desc.sem], desc.units.dimSpace,
		desc.units.dimTime, desc.units.dimCount, desc.units.scaleSpace,
		desc.units.scaleTime, desc.units.scaleCount);
	}
    }

    if (python) {
    	printf("}\n");
    }
    else {
	printf("    { NULL }\n};\n");
    }
    exit(0);
}
