//
// Copyright (c) 2014 Wind River Systems, Inc.
//
// SPDX-License-Identifier: Apache-2.0
//

#include "fmAPI.h"
#include "fmAlarmUtils.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <string>


void error(const char *add = "") {
    printf("%s\n", add);
    exit(-1);
}


void ok(const char *s = "") {
    printf("Ok\n%s%s", s, strlen(s) != 0 ? "\n" : "");
    exit(0);
}


void ok(fm_uuid_t *uuid) {
    return ok(*uuid);
}


void create_alarm(const char *al) {
    SFmAlarmDataT alarm;
    EFmErrorT rc;

    memset(&alarm, 0, sizeof(alarm));

    if (!fm_alarm_from_string(al, &alarm)) {
        error("Invalid alarm string..");
    }

    // clear uuid and let it be set by fm-mgr
    memset(alarm.uuid, 0, sizeof(*alarm.uuid));
    fm_uuid_t uuid;
    if ((rc = fm_set_fault(&alarm, &uuid)) != FM_ERR_OK) {
        std::string errstr = fm_error_from_int(rc);
        error(errstr.c_str());
    }
    ok(&uuid);
}


void delete_alarms(const char *id) {
    fm_ent_inst_t inst_id;
    EFmErrorT rc;

    memset(inst_id, 0, sizeof(inst_id));
    strncpy(inst_id, id, sizeof(inst_id) - 1);

    if ((rc = fm_clear_all(&inst_id)) != FM_ERR_OK) {
        std::string errstr = fm_error_from_int(rc);
        error(errstr.c_str());
    }
    ok();
}


void delete_alarm(const char *f) {
    AlarmFilter af;
    EFmErrorT rc;

    memset(&af, 0, sizeof(af));
    if (!fm_alarm_filter_from_string(f, &af)) {
        error("Invalid alarm filter");
    }
    if ((rc = fm_clear_fault(&af)) != FM_ERR_OK) {
        std::string errstr = fm_error_from_int(rc);
        error(errstr.c_str());
    }
    ok();
}


void get_alarm(const char *f) {
    AlarmFilter af;
    EFmErrorT rc;

    memset(&af, 0, sizeof(af));
    if (!fm_alarm_filter_from_string(f, &af)) {
        error("Invalid alarm filter");
    }

    SFmAlarmDataT ad;
    memset(&ad, 0, sizeof(ad));

    if ((rc = fm_get_fault(&af, &ad)) != FM_ERR_OK) {
        std::string errstr = fm_error_from_int(rc);
        error(errstr.c_str());
    }
    std::string s;
    fm_alarm_to_string(&ad, s);
    ok(s.c_str());
}


void get_alarms(const char *id) {
    fm_ent_inst_t inst_id;
    EFmErrorT rc;

    memset(inst_id, 0, sizeof(inst_id));
    strncpy(inst_id, id, sizeof(inst_id) - 1);

    unsigned int max_alarms = 500;
    SFmAlarmDataT *p = (SFmAlarmDataT*) \
        malloc(max_alarms * sizeof(SFmAlarmDataT));

    if (p == NULL)
        error("Not enough memory...");
    if ((rc = fm_get_faults(&inst_id, p, &max_alarms)) != FM_ERR_OK) {
        free(p);
        std::string errstr = fm_error_from_int(rc);
        error(errstr.c_str());
    }
    printf("Ok\n");

    size_t ix = 0;
    for ( ; ix < max_alarms; ++ix ) {
        std::string a;
        fm_alarm_to_string(p + ix, a);
        printf("%s\n", a.c_str());
    }
    free(p);
    exit(0);
}


void get_alarms_by_id(const char *id) {
    fm_alarm_id alm_id;
    EFmErrorT rc;

    memset(alm_id, 0, sizeof(alm_id));
    strncpy(alm_id, id, sizeof(alm_id) - 1);

    unsigned int max_alarms = 500;
    SFmAlarmDataT *p = (SFmAlarmDataT*)malloc(max_alarms*sizeof(SFmAlarmDataT));

    if (p == NULL)
        error("Not enough memory...");
    if ((rc = fm_get_faults_by_id(&alm_id, p, &max_alarms)) != FM_ERR_OK) {
        free(p);
        std::string errstr = fm_error_from_int(rc);
        error(errstr.c_str());
    }
    printf("Ok\n");

    size_t ix = 0;
    for ( ; ix < max_alarms; ++ix ) {
        std::string a;
        fm_alarm_to_string(p + ix, a);
        printf("%s\n", a.c_str());
    }
    free(p);
    exit(0);
}


int main(int argc, char **argv) {
    int c;

    if (argc < 3) {
        error("Wrong arguments");
    }
    while ((c = getopt(argc, argv, "c:d:D:g:G:A:"))) {
        switch (c) {
        case 'c':
            create_alarm(optarg);
            break;
        case 'd':
            delete_alarm(optarg);
            break;
        case 'D':
            delete_alarms(optarg);
            break;
        case 'g':
            get_alarm(optarg);
            break;
        case 'G':
            get_alarms(optarg);
            break;
        case 'A':
            get_alarms_by_id(optarg);
            break;
        default:
            error("Invalid option...");
            break;
        }
    }

    return 0;
}