#include <iostream>
#include <stdlib.h>

#include "yocto_api.h"
using namespace std;


static int upgradeSerialList(vector<string> allserials)
{
  string      errmsg;


  for (std::vector<string>::iterator it = allserials.begin() ; it != allserials.end();
       ++it) {
    string serial = *it;
    YModule *module = YModule::FindModule(serial);
    string product = module->get_productName();
    string current = module->get_firmwareRelease();

    // check if a new firmare is available on yoctopuce.com
    string newfirm = module->checkFirmware("www.yoctopuce.com", true);
    if (newfirm == "") {
      cout << product << " " << serial << "(rev=" << current << ") is up to date" << endl;
    } else {
      cout << product << " " << serial << "(rev=" << current <<
           ") need be updated with firmare : " << endl;
      cout << "    " << newfirm << endl;
      // execute the firmware upgrade
      YFirmwareUpdate update = module->updateFirmware(newfirm);
      int status = update.startUpdate();
      do {
        int newstatus = update.get_progress();
        if (newstatus != status)
          cout << newstatus << "% " << update.get_progressMessage() << endl;
        YAPI::Sleep(500, errmsg);
        status = newstatus;
      } while (status < 100 && status >= 0);
      if (status < 0) {
        cout << "Firmware Update failed: " << update.get_progressMessage() << endl;
        exit(1);
      } else {
        if (module->isOnline()) {
          cout << status << "% Firmware Updated Successfully!" << endl;
        } else {
          cout << status << " Firmware Update failed: module " << serial << " is not online" <<
               endl;
          exit(1);
        }
      }
    }
  }
  return 0;
}

int main(int argc, const char * argv[])
{
  int i;
  string      errmsg;
  vector<string> hubs;
  vector<string> shield;
  vector<string> devices;

  // Setup the API to use local USB devices
  if(YAPI::RegisterHub("usb", errmsg) != YAPI_SUCCESS) {
    cerr << "RegisterHub error: " << errmsg << endl;
    return 1;
  }
  for (i = 1; i < argc; i++) {
    string hub_url = string(argv[i]);
    cout << "Update module connected to hub " << hub_url << endl;
    if(YAPI::RegisterHub(hub_url, errmsg) != YAPI_SUCCESS) {
      cerr << "RegisterHub error: " << errmsg << endl;
      return 1;
    }
  }
  //first step construct the list of all hub /shield and devices connected
  YModule *module = YModule::FirstModule();
  while (module) {
    string product = module->get_productName();
    string serial  = module->get_serialNumber();
    if (product == "YoctoHub-Shield") {
      shield.push_back(serial);
    } else if (product.substr(0, 9) == "YoctoHub-") {
      hubs.push_back(serial);
    } else if (product != "VirtualHub") {
      devices.push_back(serial);
    }
    module = module->nextModule();
  }
  // first upgrades all Hubs...
  upgradeSerialList(hubs);
  // ... then all shield..
  upgradeSerialList(shield);
  // ... and finaly all devices
  upgradeSerialList(devices);
  cout << "All devices are now up to date" << endl;
  YAPI::FreeAPI();
  return 0;
}
