// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#define _POSIX_C_SOURCE 200809L

#define _GNU_SOURCE
#define _DARWIN_C_SOURCE

#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>

#include "netprotocol.h"

#define MAX_DEVICES 255

static device_info_t devices[MAX_DEVICES];
static uint32_t devices_count = 0;

static const char* appname;

static bool has_device(const char* nodename) {
  for (uint32_t i = 0; i < devices_count; ++i) {
    if (!strncmp(devices[i].nodename, nodename, sizeof(devices[i].nodename))) {
      return true;
    }
  }
  return false;
}

static device_info_t* get_device(const char* nodename) {
  for (uint32_t i = 0; i < devices_count; ++i) {
    if (!strncmp(devices[i].nodename, nodename, sizeof(devices[i].nodename))) {
      return &devices[i];
    }
  }
  return NULL;
}

static device_info_t* add_device(device_info_t* device) {
  device_info_t* known_device = get_device(device->nodename);
  if (!known_device) {
    if (devices_count > MAX_DEVICES) {
      return NULL;
    }
    known_device = &devices[devices_count];
    devices_count++;
    strncpy(known_device->nodename, device->nodename, sizeof(known_device->nodename));
  }
  strncpy(known_device->inet6_addr_s, device->inet6_addr_s, INET6_ADDRSTRLEN);
  memcpy(&known_device->inet6_addr, &device->inet6_addr, sizeof(known_device->inet6_addr));
  known_device->state = device->state;
  known_device->bootloader_port = device->bootloader_port;
  known_device->bootloader_version = device->bootloader_version;
  return known_device;
}

static bool on_device(device_info_t* device, void* cookie) {
  if (!has_device(device->nodename)) {
    if (device->state == UNKNOWN) {
      device->state = OFFLINE;
    }
    const char* state = "unknown";
    switch (device->state) {
      case UNKNOWN:
        state = "unknown";
        break;
      case OFFLINE:
        state = "offline";
        break;
      case DEVICE:
        state = "device";
        break;
      case BOOTLOADER:
        state = "bootloader";
        break;
    }

    // TODO(jimbe): Print the type of the device based on the vendor id of the mac address.
    fprintf(stdout, "%10s %s", state, device->nodename);
    if (device->inet6_addr.sin6_scope_id != 0) {
      fprintf(stdout, " (%s/%d)", device->inet6_addr_s, device->inet6_addr.sin6_scope_id);
    }
    if (device->state == BOOTLOADER) {
      fprintf(stdout, " [Bootloader version 0x%08X listening on %d]", device->bootloader_version,
              device->bootloader_port);
    }
    fprintf(stdout, "\n");
    if (add_device(device) == NULL) {
      return false;
    }
  }
  return true;
}

static void usage(void) {
  fprintf(stderr, "usage: %s [options]\n", appname);
  netboot_usage(false);
}

int main(int argc, char** argv) {
  appname = argv[0];
  int index = netboot_handle_getopt(argc, argv);
  if (index < 0) {
    usage();
    return -1;
  }

  if (netboot_discover(NB_SERVER_PORT, NULL, on_device, NULL)) {
    fprintf(stderr, "Failed to discover\n");
    return 1;
  }
  return 0;
}
