// Copyright (c) 2012 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.


#ifndef PLUGIN_GOBI_MODEM_H_
#define PLUGIN_GOBI_MODEM_H_

#include <glib.h>
#include <pthread.h>
#include <base/basictypes.h>
// TODO(ers) remove following #include once logging spew is resolved
#include <base/logging.h>
#include <gtest/gtest_prod.h>  // For FRIEND_TEST
#include <map>
#include <string>
#include <set>

#include <cromo/cromo_server.h>
#include <cromo/modem.h>
#include <cromo/modem_server_glue.h>
#include <cromo/modem-simple_server_glue.h>
#include <cromo/properties_server_glue.h>
#include <cromo/utilities.h>
#include <metrics/metrics_library.h>
#include <mm/mm-modem.h>

#include "modem_gobi_server_glue.h"
#include "gobi_sdk_wrapper.h"
#include "metrics_stopwatch.h"

// TODO(rochberg)  Fix namespace pollution
#define METRIC_BASE_NAME "Network.3G.Gobi."

#define DEFINE_ERROR(name) \
  extern const char* k##name##Error;
#define DEFINE_MM_ERROR(name, str) \
  extern const char* kError##name;
#include "gobi_modem_errors.h"
#undef DEFINE_ERROR
#undef DEFINE_MM_ERROR


const char* QMIReturnCodeToMMError(unsigned int qmicode);
const char* QMICallFailureToMMError(unsigned int qmireason);
unsigned int QMIReasonToMMReason(unsigned int qmireason);

#define ENSURE_SDK_SUCCESS_WITH_RESULT(function, rc, errtype, result) \
    do {                                                   \
      if (rc != 0) {                                       \
        const char *errname = QMIReturnCodeToMMError(rc);  \
        if (errname != NULL)                               \
          error.set(errname, #function);                   \
        else                                               \
          error.set(errtype, #function);                   \
        LOG(WARNING) << #function << " failed : " << rc;   \
        return result;                                     \
      }                                                    \
    } while (0)                                            \

#define ENSURE_SDK_SUCCESS(function, rc, errtype)   \
        ENSURE_SDK_SUCCESS_WITH_RESULT(function, rc, errtype,)

// from mm-modem.h in ModemManager. This enum
// should move into an XML file to become part
// of the DBus API
typedef enum {
    MM_MODEM_STATE_UNKNOWN = 0,
    MM_MODEM_STATE_DISABLED = 10,
    MM_MODEM_STATE_DISABLING = 20,
    MM_MODEM_STATE_ENABLING = 30,
    MM_MODEM_STATE_ENABLED = 40,
    MM_MODEM_STATE_SEARCHING = 50,
    MM_MODEM_STATE_REGISTERED = 60,
    MM_MODEM_STATE_DISCONNECTING = 70,
    MM_MODEM_STATE_CONNECTING = 80,
    MM_MODEM_STATE_CONNECTED = 90,

    MM_MODEM_STATE_LAST = MM_MODEM_STATE_CONNECTED
} MMModemState;

static const size_t kDefaultBufferSize = 128;

class Carrier;
class CromoServer;
class GobiModem;
class GobiModemHandler;
class SessionStarter;
class InjectedFaults;
class GobiModemHelper;

class PendingEnable;

class ScopedGSource {
 public:
  ScopedGSource() : id_(0) { }
  ~ScopedGSource() { Remove(); }

  // Remove old timeout if exists and add a new one
  guint TimeoutAddFull(gint priority,
                       guint interval,
                       GSourceFunc function,
                       gpointer data,
                       GDestroyNotify notify) {
    Remove();
    id_ = g_timeout_add_seconds_full(
        priority, interval, function, data, notify);
    return id_;
  }

  void Remove(void) {
    if (id_) {
      g_source_remove(id_);
      id_ = 0;
    }
  }
  DISALLOW_COPY_AND_ASSIGN(ScopedGSource);
 private:
  uint32 id_;
};

class GobiModem
    : public Modem,
      public org::freedesktop::ModemManager::Modem_adaptor,
      public org::freedesktop::ModemManager::Modem::Simple_adaptor,

      public org::chromium::ModemManager::Modem::Gobi_adaptor,
      public org::freedesktop::DBus::Properties_adaptor,
      public DBus::IntrospectableAdaptor,
      public DBus::PropertiesAdaptor,
      public DBus::ObjectAdaptor {
 public:
  enum NetworkPreference {
    kNetworkPreferenceAutomatic = 0,
    kNetworkPreferenceCdma1xRtt = 1,
    kNetworkPreferenceCdmaEvdo = 2,
    kNetworkPreferenceGsm = 3,
    kNetworkPreferenceWcdma = 4
  };

  typedef std::map<ULONG, int> StrengthMap;

  GobiModem(DBus::Connection& connection,
            const DBus::Path& path,
            const gobi::DeviceElement &device,
            gobi::Sdk *sdk,
            GobiModemHelper *helper);
  virtual ~GobiModem();

  virtual void Init();

  int last_seen() {return last_seen_;}
  void set_last_seen(int scan_count) {
    last_seen_ = scan_count;
  }

  uint32_t mm_state() { return mm_state_; }
  void SetMmState(uint32_t new_state, uint32_t reason);

  static void set_handler(GobiModemHandler* handler) { handler_ = handler; }

  // Called by the SDK wrapper when it receives an error that requires
  // that the modem be reset.  Posts a main-thread callback that
  // power cycles the modem.
  static void SinkSdkError(const std::string& modem_path,
                           const std::string& sdk_function,
                           ULONG error);

  std::string GetUSBAddress();

  // Modem methods.
  virtual ModemAdaptor *modem_adaptor() {
    return static_cast<ModemAdaptor *>(this);
  }

  virtual SimpleAdaptor *simple_adaptor() {
    return static_cast<SimpleAdaptor *>(this);
  }

  virtual CdmaAdaptor *cdma_adaptor() {
    LOG(WARNING) << "Modem::cdma_adaptor() called on non-CDMA modem.";
    return NULL;
  }

  // DBUS Methods: Modem
  virtual void Enable(const bool& enable, DBus::Error& error);
  virtual void Connect(const std::string& number, DBus::Error& error);
  virtual void Disconnect(DBus::Error& error);
  virtual void FactoryReset(const std::string& number, DBus::Error& error);

  virtual ::DBus::Struct<
  uint32_t, uint32_t, uint32_t, uint32_t> GetIP4Config(DBus::Error& error);

  virtual ::DBus::Struct<
    std::string, std::string, std::string> GetInfo(DBus::Error& error);
  virtual void Reset(DBus::Error& error);

  // DBUS Methods: ModemSimple
  virtual void Connect(const utilities::DBusPropertyMap& properties,
                       DBus::Error& error);

  // Contract addition: GetStatus never fails, it simply does not set
  // properties it cannot determine.
  virtual utilities::DBusPropertyMap GetStatus(DBus::Error& error);

  // DBUS Methods: ModemGobi
  virtual void SetCarrier(const std::string& image, DBus::Error& error);
  virtual void SoftReset(DBus::Error& error);
  virtual void PowerCycle(DBus::Error& error);
  virtual void RequestEvents(const std::string& events, DBus::Error& error);
  virtual void SetAutomaticTracking(const bool& service_enable,
                                    const bool& port_enable,
                                    DBus::Error& error);
  virtual void InjectFault(const std::string& name,
                           const int32_t &value,
                           DBus::Error& error);
  virtual void SetNetworkPreference(const int32_t &value,
                                    DBus::Error& error);
  virtual void ForceModemActivatedStatus(DBus::Error& error);

  void ClearIdleCallbacks();

 protected:
  struct SerialNumbers {
    std::string esn;
    std::string imei;
    std::string meid;
  };

  static const int kNumStartDataSessionRetries;

  void ApiConnect(DBus::Error& error);
  ULONG ApiDisconnect(void);
  bool IsApiConnected() { return connected_modem_ != NULL; }
  virtual uint32_t CommonGetSignalQuality(DBus::Error& error);
  void GetSignalStrengthDbm(int& strength,
                            StrengthMap *interface_to_strength,
                            DBus::Error& error);

  // Read power state from the modem; update Enabled and mm_state_
  void GetPowerState();

  virtual void RegisterCallbacks();
  void ResetModem(DBus::Error& error);

  void GetSerialNumbers(SerialNumbers* out, DBus::Error &error);
  void LogGobiInformation();

  // TODO(cros-connectivity):  Move these to a utility class
  static unsigned long MapDbmToPercent(INT8 signal_strength_dbm);
  static unsigned long MapDataBearerToRfi(ULONG data_bearer_technology);

  // Send the return for the outstanding dbus call associated with *tag.
  void FinishDeferredCall(DBus::Tag *tag, const DBus::Error &error);

  // This does not use the callback args mechanism below.
  void SessionStarterDoneCallback(SessionStarter *starter);

  unsigned int QCStateToMMState(ULONG qcstate);

  struct CallbackArgs {
    CallbackArgs() : path(NULL) { }
    explicit CallbackArgs(DBus::Path *path) : path(path) { }
    ~CallbackArgs() { delete path; }
    DBus::Path* path;
   private:
    DISALLOW_COPY_AND_ASSIGN(CallbackArgs);
  };

  struct CallbackArgsWrapper {
    CallbackArgsWrapper() : callback(NULL), callback_id(0), args(NULL) { }
    ~CallbackArgsWrapper() { delete args; }
    GSourceFunc callback;
    guint callback_id;
    CallbackArgs *args;
   private:
    DISALLOW_COPY_AND_ASSIGN(CallbackArgsWrapper);
  };

  static void PostCallbackRequest(GSourceFunc callback,
                                  CallbackArgs* args) {
    pthread_mutex_lock(&modem_mutex_.mutex_);
    if (connected_modem_ && !connected_modem_->getting_deallocated_) {
      args->path = new DBus::Path(connected_modem_->path());
      CallbackArgsWrapper *args_wrapper = new CallbackArgsWrapper();
      args_wrapper->args = args;
      args_wrapper->callback = callback;
      args_wrapper->callback_id =
          g_idle_add(ExecuteCallbackRequest, args_wrapper);
      connected_modem_->idle_callback_ids_.insert(args_wrapper->callback_id);
    } else {
      delete args;
    }
    pthread_mutex_unlock(&modem_mutex_.mutex_);
  }

  static gboolean ExecuteCallbackRequest(gpointer data) {
    CallbackArgsWrapper *args_wrapper =
        reinterpret_cast<CallbackArgsWrapper*>(data);
    bool run_callback = false;
    pthread_mutex_lock(&modem_mutex_.mutex_);
    if (connected_modem_ && !connected_modem_->getting_deallocated_) {
      connected_modem_->idle_callback_ids_.erase(args_wrapper->callback_id);
      run_callback = true;
    }
    pthread_mutex_unlock(&modem_mutex_.mutex_);
    if (run_callback)
      args_wrapper->callback(args_wrapper->args);
    delete args_wrapper;
    return FALSE;
  }

  struct SessionStateArgs : public CallbackArgs {
    SessionStateArgs(ULONG state,
                     ULONG session_end_reason)
      : state(state),
        session_end_reason(session_end_reason) { }
    ULONG state;
    ULONG session_end_reason;
  };

  static void SessionStateCallbackTrampoline(ULONG state,
                                             ULONG session_end_reason) {
    PostCallbackRequest(SessionStateCallback,
                        new SessionStateArgs(state,
                                             session_end_reason));
  }
  static gboolean SessionStateCallback(gpointer data);

  struct DataBearerTechnologyArgs : public CallbackArgs {
    DataBearerTechnologyArgs(ULONG technology) : technology(technology) {}
    ULONG technology;
  };

  static void DataBearerCallbackTrampoline(ULONG technology) {
    // ignore the supplied argument
    PostCallbackRequest(DataBearerTechnologyCallback,
                        new DataBearerTechnologyArgs(technology));
  }
  static gboolean DataBearerTechnologyCallback(gpointer data);

  static void RoamingIndicatorCallbackTrampoline(ULONG roaming) {
    // ignore the supplied argument
    PostCallbackRequest(RegistrationStateCallback, new CallbackArgs());
  }
  static void PowerCallbackTrampoline(ULONG power_mode) {
    // ignore the supplied argument
    PostCallbackRequest(PowerCallback, new CallbackArgs());
  }
  static gboolean PowerCallback(gpointer data);

  static void RFInfoCallbackTrampoline(ULONG iface, ULONG bandclass,
                                       ULONG channel) {
    // ignore the supplied arguments
    PostCallbackRequest(RegistrationStateCallback, new CallbackArgs());
  }
  static gboolean RegistrationStateCallback(gpointer data);

  struct SignalStrengthArgs : public CallbackArgs {
    SignalStrengthArgs(INT8 signal_strength,
                       ULONG radio_interface)
      : signal_strength(signal_strength),
        radio_interface(radio_interface) { }
    INT8 signal_strength;
    ULONG radio_interface;
  };

  static void SignalStrengthCallbackTrampoline(INT8 signal_strength,
                                               ULONG radio_interface) {
    PostCallbackRequest(SignalStrengthCallback,
                        new SignalStrengthArgs(signal_strength,
                                               radio_interface));
  }
  static gboolean SignalStrengthCallback(gpointer data);

  struct DormancyStatusArgs : public CallbackArgs {
    DormancyStatusArgs(ULONG status) : status(status) { }
    ULONG status;
  };

  static void DormancyStatusCallbackTrampoline(ULONG status) {
    PostCallbackRequest(DormancyStatusCallback,
                        new DormancyStatusArgs(status));
  }

  static gboolean DormancyStatusCallback(gpointer data);

  struct DataCapabilitiesArgs : public CallbackArgs {
    DataCapabilitiesArgs(BYTE num_caps, BYTE* data)
      : num_data_caps(num_caps) {
      ULONG* dcp = reinterpret_cast<ULONG*>(data);
      if (num_data_caps > 12)
        num_data_caps = 12;
      for (int i = 0; i < num_data_caps; i++)
        data_caps[i] = dcp[i];
    }
    BYTE num_data_caps;
    // undocumented: the SDK limits the number of
    // data capabilities reported to 12
    ULONG data_caps[12];
  };

  static void DataCapabilitiesCallbackTrampoline(BYTE num_data_caps,
                                                 BYTE* data_caps) {
    PostCallbackRequest(DataCapabilitiesCallback,
                        new DataCapabilitiesArgs(num_data_caps, data_caps));
  }
  static gboolean DataCapabilitiesCallback(gpointer data);

  struct SdkErrorArgs : public CallbackArgs {
    SdkErrorArgs(ULONG error) : error(error) { }
    ULONG error;
  };
  static gboolean SdkErrorHandler(gpointer data);

  // Set DBus-exported properties
  void SetDeviceProperties();
  void SetModemProperties();
  virtual void SetTechnologySpecificProperties() = 0;
  virtual void GetTechnologySpecificStatus(
      utilities::DBusPropertyMap* properties) = 0;
  virtual bool CheckEnableOk(DBus::Error &error) = 0;

  // Handlers for events delivered as callbacks by the SDK. These
  // all run in the main thread.
  virtual void RegistrationStateHandler() = 0;
  virtual void DataCapabilitiesHandler(BYTE num_data_caps,
                               ULONG* data_caps) = 0;
  virtual void SignalStrengthHandler(INT8 signal_strength,
                                     ULONG radio_interface) = 0;

  virtual void SessionStateHandler(ULONG state, ULONG session_end_reason);
  virtual void DataBearerTechnologyHandler(ULONG technology);
  virtual void PowerModeHandler();

  static GobiModemHandler *handler_;
  // Wraps the Gobi SDK for dependency injection
  gobi::Sdk *sdk_;
  scoped_ptr<GobiModemHelper> modem_helper_;
  gobi::DeviceElement device_;
  int last_seen_;  // Updated every scan where the modem is present
  // Mirrors the DBus "State" property. This variable exists because
  // the DBus properties are essentially write-only.
  uint32_t mm_state_;

  ULONG session_id_;
  bool signal_available_;

  std::string sysfs_path_;

  struct mutex_wrapper_ {
    mutex_wrapper_() { pthread_mutex_init(&mutex_, NULL); }
    pthread_mutex_t mutex_;
  };
  static GobiModem *connected_modem_;
  static mutex_wrapper_ modem_mutex_;

  bool exiting_;
  bool device_resetting_;
  bool getting_deallocated_;

  std::set<guint> idle_callback_ids_;

  bool session_starter_in_flight_;
  scoped_ptr<PendingEnable> pending_enable_;

  ScopedGSource retry_disable_callback_source_;
  void RescheduleDisable();
  static void CleanupRetryDisableCallback(gpointer data);
  static gboolean RetryDisableCallback(gpointer data);
  bool EnableHelper(const bool& enable, DBus::Error& error,
                    const bool& user_initiated);
  void FinishEnable(const DBus::Error &error);
  void PerformDeferredDisable();

  static gobi::RegistrationState GetRegistrationState(gobi::Sdk *sdk);

  friend class GobiModemTest;

  // Return true if a data session is in the process of starting or
  // has started
  bool is_connecting_or_connected();

  // Call the Gobi API to stop a data session
  ULONG StopDataSession(ULONG session_id);

  // Force a disconnect of a data session, or stop the process of
  // starting a datasession
  ULONG ForceDisconnect();
  bool StartExit();
  bool ExitOk();

  // Resets the device by kicking it off the USB and allowing it back
  // on.  Reason is a QCWWAN error code for logging/metrics, or 0 for
  // 'externally initiated'
  void ExitAndResetDevice(ULONG reason);
  // Helper that compresses reason to a small int and mails to UMA
  void RecordResetReason(ULONG reason);

  bool CanMakeMethodCalls(void);

  std::string hooks_name_;

  friend bool StartExitTrampoline(void *arg);
  friend bool ExitOkTrampoline(void *arg);

  scoped_ptr<MetricsLibraryInterface> metrics_lib_;

  MetricsStopwatch disconnect_time_;
  MetricsStopwatch registration_time_;
  std::map<std::string, int32_t> injected_faults_;

  // This ought to go on the gobi modem XML interface, but dbus-c++ can't handle
  // enums, and all the ways of hacking around it seem worse than just using
  // strings and translating to the enum when we get the DBus call.
  enum {
    GOBI_EVENT_DORMANCY = 0,
    GOBI_EVENT_MAX
  };

  static int EventKeyToIndex(const char *key);
  void RequestEvent(const std::string req, DBus::Error& error);
  bool event_enabled[GOBI_EVENT_MAX];

  // Sets the Enabled property and emits a property changed signal.
  void SetEnabled(bool enabled);

  FRIEND_TEST(GobiModemTest, GetSignalStrengthDbmDisconnected);
  FRIEND_TEST(GobiModemTest, GetSignalStrengthDbmConnected);

  friend class SessionStarter;
  friend class PendingEnable;
  friend class ScopedApiConnection;
  friend class Gobi3KModemHelper;  // a bad idea, but necessary until
                                   // code is restructured

  DISALLOW_COPY_AND_ASSIGN(GobiModem);
};

class ScopedApiConnection {
 public:
  ScopedApiConnection(GobiModem &modem) : modem_(modem),
                                   was_connected_(modem_.IsApiConnected()) { }
  ~ScopedApiConnection() {
    if (!was_connected_ && modem_.IsApiConnected())
      modem_.ApiDisconnect();
  }

  void ApiConnect(DBus::Error& error) {
    if (!was_connected_)
      modem_.ApiConnect(error);
  }

  // Force an immediate disconnect independent of prior state
  void ApiDisconnect() {
    // Prevent auto disconnect on destruction by faking we had been connected
    was_connected_ = true;
    modem_.ApiDisconnect();
  }

 private:
  GobiModem &modem_;
  bool was_connected_;
};

class GobiModemHelper {
 public:
  GobiModemHelper(gobi::Sdk* sdk) : sdk_(sdk) { };
  virtual ~GobiModemHelper() { };

  virtual void SetCarrier(GobiModem *modem,
                          GobiModemHandler *handler,
                          const std::string& carrier_name,
                          DBus::Error& error) = 0;

  DISALLOW_COPY_AND_ASSIGN(GobiModemHelper);

 protected:
  static const char kErrorUnknownCarrier[];

  gobi::Sdk* sdk_;
};

#endif  // PLUGIN_GOBI_MODEM_H_
