// Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <dlfcn.h>
#include <glib-object.h>
#include <map>
#include <vector>

#include <base/logging.h>
#include <base/values.h>

#include "chromeos_cros_api.h"  // NOLINT
#include "chromeos_network.h"  // NOLINT
// TODO(stevenjb): Remove testing of deprecated code; add new tests.
#include "chromeos_network_deprecated.h"  // NOLINT
#include "chromeos/dbus/dbus.h"  // NOLINT
#include "chromeos/glib/object.h"  // NOLINT
#include "monitor_utils.h" //NOLINT


void DumpServices(const chromeos::SystemInfo* info);
void DumpDataPlans(const char* service_path,
                   const chromeos::CellularDataPlanList* data_plan_list);
void PrintProperty(const char* path,
                   const char* key,
                   const Value* value);

// Callback is an example of how to use the network monitoring functionality.
class CallbackMonitorNetwork {
 public:
  // You can store whatever state is needed in the function object.
  explicit CallbackMonitorNetwork() :
    count_(0) {
  }

  // Note, you MUST copy the service status struct since it will be freed
  // the moment this function returns.
  //
  // DO NOT DO THIS
  // Struct my_status = status;
  //
  // DO THIS INSTEAD
  // Struct my_status = {};
  // my_status = MakeACopyOf(status);
  // ...
  static void Run(void* object,
                  const char* path,
                  const char* key,
                  const Value* value) {
    PrintProperty(path, key, value);
    if (strcmp(key, "Services") == 0) {
      chromeos::SystemInfo* info = chromeos::GetSystemInfo();
      DumpServices(info);
      chromeos::FreeSystemInfo(info);
    }
    CallbackMonitorNetwork* self = static_cast<CallbackMonitorNetwork*>(object);
    ++self->count_;
  }

 private:
  int count_;
};

// CallbackMonitorDataPlan is an example of how to use the cellular
// data plan monitoring functionality.
class CallbackMonitorDataPlan {
 public:
  explicit CallbackMonitorDataPlan() :
    count_(0) {
  }

  static void Run(void* object,
                  const char* path,
                  const chromeos::CellularDataPlanList* data) {
    DumpDataPlans(path, data);

    CallbackMonitorDataPlan* self =
        static_cast<CallbackMonitorDataPlan*>(object);
    ++self->count_;
  }

 private:
  int count_;
};

struct ServiceMonitor {
  ServiceMonitor() : monitor(NULL), callback(NULL), last_scangen(0) { }
  ~ServiceMonitor() { delete callback; }
  chromeos::PropertyChangeMonitor monitor;
  CallbackMonitorNetwork *callback;
  int last_scangen;
  static int scangen;
};

int ServiceMonitor::scangen;

typedef std::map<std::string, ServiceMonitor*> MonitorMap;
MonitorMap monitor_map;

void PrintProperty(const char* path,
                   const char* key,
                   const Value* value) {
    std::string prelude("PropertyChanged [");
    prelude += path;
    prelude += "] ";
    prelude += key;
    prelude += " : ";
    if (value->IsType(Value::TYPE_STRING)) {
      std::string strval;
      value->GetAsString(&strval);
      LOG(INFO) << prelude << "\"" << strval << "\"";
    } else if (value->IsType(Value::TYPE_BOOLEAN)) {
      bool boolval;
      value->GetAsBoolean(&boolval);
      LOG(INFO) << prelude << boolval;
    }  else if (value->IsType(Value::TYPE_INTEGER)) {
      int intval;
      value->GetAsInteger(&intval);
      LOG(INFO) << prelude << intval;
    } else if (value->IsType(Value::TYPE_LIST)) {
      const ListValue* list = static_cast<const ListValue*>(value);
      Value *itemval;
      std::string liststr;
      size_t index = 0;
      while (list->Get(index, &itemval)) {
        if (!itemval->IsType(Value::TYPE_STRING)) {
          ++index;
          continue;
        }
        std::string itemstr;
        itemval->GetAsString(&itemstr);
        liststr += itemstr;
        ++index;
        if (index < list->GetSize())
          liststr += ", ";
      }
      LOG(INFO) << prelude << "\"" << liststr << "\"";
    } else if (value->IsType(Value::TYPE_DICTIONARY)) {
      const DictionaryValue* dict = static_cast<const DictionaryValue*>(value);
      std::string items;
      std::string itemval;
      size_t n = 0;
      DictionaryValue::key_iterator iter = dict->begin_keys();
      while (iter != dict->end_keys()) {
        std::string key = *iter;
        items += "{'" + key + "': '";
        if (dict->GetStringWithoutPathExpansion(key, &itemval))
          items += itemval + "'}";
        else
          items += "<not-a-string>'}";
        if (n < dict->size())
          items += ", ";
        ++iter;
        ++n;
      }
      LOG(INFO) << prelude << items;
    } else
      LOG(INFO) << prelude << "<type " << value->GetType() << ">";
}

void DumpDeviceInfo(const chromeos::DeviceInfo& device,
                    chromeos::ConnectionType type) {
  LOG(INFO) << "      Name:" << device.name
            << ", Type:" << device.type
            << ", Scanning: " << device.scanning;
  if (type == chromeos::TYPE_CELLULAR) {
    LOG(INFO) << "      Carrier:" << device.carrier;
    LOG(INFO) << "      MEID=" << device.MEID
              << ", IMEI=" << device.IMEI
              << ", IMSI=" << device.IMSI
              << ", ESN=" << device.ESN
              << ", MDN=" << device.MDN
              << ", MIN=" << device.MIN;
    LOG(INFO) << "      ModelID=" << device.model_id
              << ", Manufacturer=" << device.manufacturer;
    LOG(INFO) << "      Firmware=" << device.firmware_revision
              << ", Hardware=" << device.hardware_revision;
    LOG(INFO) << "      Last Update=" << device.last_update
              << ", PRL Version=" << device.PRL_version;
  }
}

void DumpCarrierInfo(const chromeos::CarrierInfo& carrier) {
  LOG(INFO) << "      Operator:" << carrier.operator_name
            << ", Code=" << carrier.operator_code;
  LOG(INFO) << "      Payment URL:" << carrier.payment_url;
}

void DumpService(const chromeos::ServiceInfo& info) {
  const char* passphrase;
  if (info.passphrase != NULL && strlen(info.passphrase) != 0)
    passphrase = "******";
  else
    passphrase = "\"\"";

  LOG(INFO) << "  \"" << info.name << "\"";
  LOG(INFO) << "    Service=" << info.service_path
            << ", Name=" << info.name;
  LOG(INFO) << "    Type=" << info.type
            << ", Active=" << info.is_active;
  LOG(INFO) << "    Mode=" << info.mode
            << ", Security=" << info.security
            << ", State=" << info.state
            << ", Error=" << info.error;
  LOG(INFO) << "    PassphraseRequired=" << info.passphrase_required
            << ", Passphrase=" << passphrase;
  LOG(INFO) << "    Identity=" << info.identity
            << ", CertPath=" << info.cert_path;
  LOG(INFO) << "    Strength=" << info.strength
            << ", Favorite=" << info.favorite
            << ", AutoConnect=" << info.auto_connect;
  if (info.device_path)
    LOG(INFO) << "    Device=" << info.device_path;
  if (info.device_info)
    DumpDeviceInfo(*info.device_info, info.type);
  if (info.type == chromeos::TYPE_CELLULAR)
    LOG(INFO) << "    Activation State=" << info.activation_state
            << ", Technology=" << info.network_technology
            << ", RoamingState=" << info.roaming_state
            << ", ConnectivityState=" << info.connectivity_state
            << ", (RestrictedPool=" << info.restricted_pool << ")";
  if (info.carrier_info)
    DumpCarrierInfo(*info.carrier_info);
}

// Dumps the contents of ServiceStatus to the log.
void DumpServices(const chromeos::SystemInfo* info) {
  if (info == NULL)
    return;

  LOG(INFO) << "Network status:";
  ++ServiceMonitor::scangen;
  for (int i = 0; i < info->service_size; i++) {
    chromeos::ServiceInfo *sinfo = &info->services[i];
    DumpService(*sinfo);

    ServiceMonitor *servmon = monitor_map[sinfo->service_path];
    if (servmon == NULL) {
      LOG(INFO) << "New service " << sinfo->service_path;
      servmon = new ServiceMonitor;
      servmon->callback = new CallbackMonitorNetwork();
      monitor_map[sinfo->service_path] = servmon;
    }
    servmon->last_scangen = ServiceMonitor::scangen;
    // For any service that has just entered the ready (i..e, connected)
    // state, start monitoring it for property changes. For any service
    // that has just left the ready state, stop monitoring it. Also
    // start monitoring if there is just one service.
    if (sinfo->state == chromeos::STATE_READY ||
        sinfo->type == chromeos::TYPE_CELLULAR) {
      if (servmon->monitor == NULL) {
        LOG(INFO) << "Start monitoring service " << sinfo->service_path;
        servmon->monitor = chromeos::MonitorNetworkService(
            &CallbackMonitorNetwork::Run,
            sinfo->service_path,
            servmon->callback);
      }
    } else if (servmon->monitor != NULL) {
        LOG(INFO) << "Stop monitoring service " << sinfo->service_path;
        chromeos::DisconnectPropertyChangeMonitor(servmon->monitor);
        servmon->monitor = NULL;
    }
  }
  // Go through monitor_map and remove mappings for
  // services that are no longer in the service list.
  LOG(INFO) << "Removing services.";
  MonitorMap::iterator it;
  for (it = monitor_map.begin(); it != monitor_map.end(); ++it) {
    ServiceMonitor* servmon = it->second;
    if (servmon->last_scangen != ServiceMonitor::scangen)  {
      if (servmon->monitor != NULL) {
        LOG(INFO) << "Service " << it->first << " gone, stop monitoring";
        chromeos::DisconnectPropertyChangeMonitor(servmon->monitor);
      } else
        LOG(INFO) << "Service " << it->first << " no longer present";
      monitor_map.erase(it);
      delete servmon;
    }
  }
}

void DumpDataPlans(const char* modem_service_path,
                   const chromeos::CellularDataPlanList* data_plan_list) {
  LOG(INFO) << "Data Plans for: '" << modem_service_path;
  for (unsigned int i = 0; i < data_plan_list->plans_size; i++) {
    const chromeos::CellularDataPlanInfo* data =
        data_plan_list->GetCellularDataPlan(i);
    LOG(INFO) << "Plan Name: " << data->plan_name
              << ", Type=" << data->plan_type
              << ", Update Time=" << data->update_time
              << ", Start Time=" << data->plan_start_time
              << ", End Time=" << data->plan_end_time
              << ", Data Bytes=" << data->plan_data_bytes
              << ", Bytes Used=" << data->data_bytes_used;
  }
}

// A simple example program demonstrating how to use the ChromeOS network API.
int main(int argc, const char** argv) {
  ::g_type_init();
  GMainLoop* loop = ::g_main_loop_new(NULL, false);

  DCHECK(loop) << "Failed to create main loop";
  if (!LoadCrosLibrary(argv))
    LOG(INFO) << "Failed to load cros .so";

  // Synchronous request of network info.

  LOG(INFO) << "Calling chromeos::GetSystemInfo()";
  chromeos::SystemInfo* network_info = chromeos::GetSystemInfo();
  DCHECK(network_info) << "Unable to get SystemInfo";

  LOG(INFO) << "Enabled network devices:";
  int technologies = network_info->enabled_technologies;
  if (technologies & (1 << chromeos::TYPE_ETHERNET))
    LOG(INFO) << "  ethernet";
  if (technologies & (1 << chromeos::TYPE_WIFI))
    LOG(INFO) << "  wifi";
  if (technologies & (1 << chromeos::TYPE_WIMAX))
    LOG(INFO) << "  wimax";
  if (technologies & (1 << chromeos::TYPE_BLUETOOTH))
    LOG(INFO) << "  bluetooth";
  if (technologies & (1 << chromeos::TYPE_CELLULAR))
    LOG(INFO) << "  cellular";

  DumpServices(network_info);

  // Synchronous request of data plans.

  LOG(INFO) << "Retrieving Cellular Data Plans:";
  for (int i = 0; i < network_info->service_size; ++i) {
    chromeos::ServiceInfo *sinfo = &network_info->services[i];
    if (sinfo->type != chromeos::TYPE_CELLULAR) {
      continue;
    }
    LOG(INFO) << "  Retrieving Data Plans for: " << sinfo->service_path;
    chromeos::CellularDataPlanList* data_plan_list;
    data_plan_list = chromeos::RetrieveCellularDataPlans(sinfo->service_path);

    if (data_plan_list) {
      DumpDataPlans(sinfo->service_path, data_plan_list);
      chromeos::FreeCellularDataPlanList(data_plan_list);
    } else {
      LOG(WARNING) << "  RetrieveCellularDataPlans failed for: "
          << sinfo->service_path;
    }
  }

  // Asynchronous network monitoring.

  LOG(INFO) << "Starting Monitor Network:";
  CallbackMonitorNetwork callback_network;
  chromeos::PropertyChangeMonitor connection_network =
      chromeos::MonitorNetworkManager(&CallbackMonitorNetwork::Run,
                                      &callback_network);

  // Asynchronous data plan monitoring.

  LOG(INFO) << "Starting Monitor Data Plan:";
  CallbackMonitorDataPlan callback_dataplan;
  chromeos::DataPlanUpdateMonitor connection_dataplan =
      chromeos::MonitorCellularDataPlan(&CallbackMonitorDataPlan::Run,
                                        &callback_dataplan);
  LOG(INFO) << "Requesting Cellular Data Plan Updates:";
  for (int i = 0; i < network_info->service_size; i++) {
    chromeos::ServiceInfo *sinfo = &network_info->services[i];
    if (sinfo->type == chromeos::TYPE_CELLULAR) {
      LOG(INFO) << "  Requesting Data Plan Update for: " << sinfo->service_path;
      chromeos::RequestCellularDataPlanUpdate(sinfo->service_path);
    }
  }

  LOG(INFO) << "Starting g_main_loop.";

  ::g_main_loop_run(loop);

  LOG(INFO) << "Shutting down.";

  chromeos::FreeSystemInfo(network_info);
  chromeos::DisconnectPropertyChangeMonitor(connection_network);
  chromeos::DisconnectDataPlanUpdateMonitor(connection_dataplan);

  return 0;
}
