/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * 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.
 */

#include <popt.h>

// #define LOCAL_DEBUG

/*
 * popt has been deprecated for some time, and is replaced by GNOME's glib
 * option parser. Instead of pulling in either of those dependencies, this
 * stub implements just enough of popt to get things working.
 */

poptContext poptGetContext(const char *name, int argc, const char **argv,
        const struct poptOption *options, unsigned int flags) {
    // Convert into getopt format, sanity checking our limited
    // capabilities along the way
    int count = 0;
    for (; options[count].longName; count++) {
    }

    // getopt_long expects the last element to be null
    // so allocate count + 1
    struct option *long_options = (struct option *)
            calloc(count + 1, sizeof(struct option));
    for (int i = 0; options[i].longName; i++) {
        long_options[i].name = options[i].longName;
        long_options[i].flag = 0;

        if (!options[i].val) {
            fprintf(stderr, __FILE__ ": val required\n");
            abort();
        }
        long_options[i].val = options[i].val;

        switch (options[i].argInfo) {
        case POPT_ARG_NONE:
            long_options[i].has_arg = no_argument;
            break;
        case POPT_ARG_STRING:
        case POPT_ARG_INT:
            if (!options[i].arg) {
                fprintf(stderr, __FILE__ ": arg required\n");
                abort();
            }
            long_options[i].has_arg = required_argument;
            break;
        default:
            fprintf(stderr, __FILE__ ": unsupported argInfo\n");
            abort();
        }
    }

    poptContext con = (poptContext) calloc(1, sizeof(struct _poptContext));
    con->argc = argc;
    con->argv = argv;
    con->options = options;
    con->long_options = long_options;
    return con;
}

poptContext poptFreeContext(poptContext con) {
    free(con->long_options);
    free(con);
    return 0;
}

void poptResetContext(poptContext con) {
    optind = 1;
}

void poptSetOtherOptionHelp(poptContext con, const char *text) {
    con->otherHelp = text;
}

void poptPrintUsage(poptContext con, FILE *fp, int flags) {
    fprintf(fp, "USAGE: %s %s\n", con->argv[0], con->otherHelp);
    int i = 0;
    for (; con->options[i].longName; i++) {
        fprintf(fp, "\t--%s\t%s\n", con->options[i].longName,
                con->options[i].descrip);
    }
    fprintf(fp, "\n");
}

int poptGetNextOpt(poptContext con) {
    int i = -1;
    int res = getopt_long(con->argc, (char *const *) con->argv, "",
            con->long_options, &i);
#ifdef LOCAL_DEBUG
    fprintf(stderr, "getopt_long()=%c\n", res);
#endif
    if (res <= 0 || res == '?' || i == -1) {
        return -1;
    }

    // Copy over found argument value
    switch (con->options[i].argInfo) {
    case POPT_ARG_STRING:
        *((char**) con->options[i].arg) = strdup(optarg);
        break;
    case POPT_ARG_INT:
        *((int*) con->options[i].arg) = atoi(optarg);
        break;
    }

    return res;
}

const char *poptGetArg(poptContext con) {
    const char *res = con->argv[optind++];
#ifdef LOCAL_DEBUG
    fprintf(stderr, "poptGetArg()=%s\n", res);
#endif
    return res;
}
