// $Id: econsort.c,v 1.2 2011/05/07 01:07:38 lpoulsen Exp $
//
// Copyright (c) 2010 by AFAR Communications Inc, Santa Barbara, CA 93117, USA
//
// Sort the table of discovered nodes for ECON
//
// $Log: econsort.c,v $
// Revision 1.2  2011/05/07 01:07:38  lpoulsen
// Change order of #include's
//
// Revision 1.1  2011/02/04 22:29:07  lpoulsen
// Many little fixes.
//
//

#include <time.h>
#include "afartype.h"
#include "epacket.h"
#include "eprotocol.h"
#include "util.h"
#include <assert.h>
#include "adapter.h"            // my_mac_address
#include "parser.h"
#include "uciosess.h"
#include "ucon.h"

#ifndef __APPLE__
#define ntohs(a) swap_uint16(a)
#define ntohl(a) swap_uint32(a)
#endif

// -- Local procedures


// -- Global data

extern macAddr             bcastMacAddress;
extern struct device_entry afar_device[MAX_DEVICES];

// -- Local data

// -- sort the device table ------------------------------------------------

Select sort_by_sel[] = {
    { "name",          0 },
    { "type",          0 },
    { "firmware",      0 },
    { "serial-number", 0 },
    { "ip-address",    0 },
    { "distance",      0 },
    { NULL,            0 }
};

Arg sort_args[] = {
    { "by", SELECT(sort_by_sel), 0 },
    { NULL, {UNDEF_ARG},         0 }
};

static int
compare_by(int sortby, int i, int j)
{
    int k;

    if (i == j)               return 0;
    if (i > numOfRadiosFound) return 0;
    if (j > numOfRadiosFound) return 0;

    switch (sortby)
    {
    case 0: // name
    default:
        k = strcmp(afar_device[i].radio_name, afar_device[j].radio_name);
        if (k) return k;
        // if the names are equal, use serial number as a tie-breaker
        return memcmp(afar_device[i].mac_address, afar_device[j].mac_address,
                                                  6);
    case 2: // firmware
        k = strcmp(afar_device[i].firmware, afar_device[j].firmware);
        if (k) return k;
        // if same firmware, sort by device type

    case 1: // type
        if (afar_device[i].device_type < afar_device[j].device_type)
            return -1;
        if (afar_device[i].device_type > afar_device[j].device_type)
            return 1;
        // if the types are equal, use serial-number as a tie-breaker

    case 3: // serial-number
        return memcmp(afar_device[i].mac_address, afar_device[j].mac_address,
                                                  6);

    case 4: // ip-address
        return memcmp((void *)&afar_device[i].ip_address,
                      (void *)&afar_device[j].ip_address, 4);

    case 5: // distance - most distant ones at the top
        if (afar_device[i].rtt_ms < afar_device[j].rtt_ms) return 1;
        if (afar_device[i].rtt_ms > afar_device[j].rtt_ms) return -1;
        return 0;
    }
}

void
sort_device_table(int sortby)
{
    int   i, j;

    if (numOfRadiosFound < 2)
        return;

    for (i = 1; i < numOfRadiosFound; i++) {
        for (j = i+1; j <= numOfRadiosFound; j++) {
            if (compare_by(sortby, i, j) > 0) {
                struct device_entry tmp;

                memcpy(&tmp,            &afar_device[i],
                                        sizeof(struct device_entry));
                memcpy(&afar_device[i], &afar_device[j],
                                        sizeof(struct device_entry));
                memcpy(&afar_device[j], &tmp,
                                        sizeof(struct device_entry));
            }
        }
    }
}

cmd_ret_t
econ_sort(Argument_List *a, ucio_session *s)
{
    char *tmp;
    int   sortby;

    // numOfRadiosFound = discover_radios(true, 2);
    // printf("\n%d devices were found.\n", numOfRadiosFound);
    // return CMD_SUCCESS;

    if (numOfRadiosFound <= 1)
        return CMD_SUCCESS;

    tmp = parser_get_value(a, "by");
    if (tmp == NULL) tmp = "name";
    sortby = parse_select_match(tmp, sort_by_sel);

    sort_device_table(sortby);
    show_radios(false, 0, 1, 45);

    return CMD_SUCCESS;
}

// End
