/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "wificond/client_interface_impl.h"

#include <vector>

#include <android-base/logging.h>
#include <utils/Timers.h>

#include "wificond/client_interface_binder.h"
#include "wificond/logging_utils.h"
#include "wificond/net/mlme_event.h"
#include "wificond/net/netlink_utils.h"
#include "wificond/scanning/scan_result.h"
#include "wificond/scanning/scan_utils.h"
#include "wificond/scanning/scanner_impl.h"

using android::net::wifi::nl80211::IClientInterface;
using android::net::wifi::nl80211::ISendMgmtFrameEvent;
using android::net::wifi::nl80211::NativeScanResult;
using android::sp;
using android::wifi_system::InterfaceTool;

using std::endl;
using std::string;
using std::unique_ptr;
using std::vector;

using namespace std::placeholders;

namespace android {
namespace wificond {

MlmeEventHandlerImpl::MlmeEventHandlerImpl(ClientInterfaceImpl* client_interface)
    : client_interface_(client_interface) {
}

MlmeEventHandlerImpl::~MlmeEventHandlerImpl() {
}

void MlmeEventHandlerImpl::OnConnect(unique_ptr<MlmeConnectEvent> event) {
  if (!event->IsTimeout() && event->GetStatusCode() == 0) {
    client_interface_->is_associated_ = true;
    client_interface_->RefreshAssociateFreq();
    client_interface_->bssid_ = event->GetBSSID();
  } else {
    if (event->IsTimeout()) {
      LOG(INFO) << "Connect timeout";
    }
    client_interface_->is_associated_ = false;
    client_interface_->bssid_.fill(0);
  }
}

void MlmeEventHandlerImpl::OnRoam(unique_ptr<MlmeRoamEvent> event) {
  client_interface_->is_associated_ = true;
  client_interface_->RefreshAssociateFreq();
  client_interface_->bssid_ = event->GetBSSID();
}

void MlmeEventHandlerImpl::OnAssociate(unique_ptr<MlmeAssociateEvent> event) {
  if (!event->IsTimeout() && event->GetStatusCode() == 0) {
    client_interface_->is_associated_ = true;
    client_interface_->RefreshAssociateFreq();
    client_interface_->bssid_ = event->GetBSSID();
  } else {
    if (event->IsTimeout()) {
      LOG(INFO) << "Associate timeout";
    }
    client_interface_->is_associated_ = false;
    client_interface_->bssid_.fill(0);
  }
}

void MlmeEventHandlerImpl::OnDisconnect(unique_ptr<MlmeDisconnectEvent> event) {
  client_interface_->is_associated_ = false;
  client_interface_->bssid_.fill(0);
}

void MlmeEventHandlerImpl::OnDisassociate(unique_ptr<MlmeDisassociateEvent> event) {
  client_interface_->is_associated_ = false;
  client_interface_->bssid_.fill(0);
}


ClientInterfaceImpl::ClientInterfaceImpl(
    uint32_t wiphy_index,
    const std::string& interface_name,
    uint32_t interface_index,
    const std::array<uint8_t, ETH_ALEN>& interface_mac_addr,
    InterfaceTool* if_tool,
    NetlinkUtils* netlink_utils,
    ScanUtils* scan_utils)
    : wiphy_index_(wiphy_index),
      interface_name_(interface_name),
      interface_index_(interface_index),
      interface_mac_addr_(interface_mac_addr),
      if_tool_(if_tool),
      netlink_utils_(netlink_utils),
      scan_utils_(scan_utils),
      mlme_event_handler_(new MlmeEventHandlerImpl(this)),
      binder_(new ClientInterfaceBinder(this)),
      is_associated_(false),
      frame_tx_in_progress_(false),
      frame_tx_status_cookie_(0),
      on_frame_tx_status_event_handler_([](bool was_acked) {}) {
  netlink_utils_->SubscribeMlmeEvent(
      interface_index_,
      mlme_event_handler_.get());

  netlink_utils_->SubscribeFrameTxStatusEvent(
      interface_index,
      [this](uint64_t cookie, bool was_acked) {
        if (frame_tx_in_progress_ && frame_tx_status_cookie_ == cookie) {
          on_frame_tx_status_event_handler_(was_acked);
          frame_tx_in_progress_ = false;
          frame_tx_status_cookie_ = 0;
          on_frame_tx_status_event_handler_ = [](bool was_acked) {};
        }
      });

  netlink_utils_->SubscribeChannelSwitchEvent(interface_index_,
      std::bind(&ClientInterfaceImpl::OnChannelSwitchEvent, this, _1));

  if (!netlink_utils_->GetWiphyInfo(wiphy_index_,
                               &band_info_,
                               &scan_capabilities_,
                               &wiphy_features_)) {
    LOG(ERROR) << "Failed to get wiphy info from kernel";
  }
  LOG(INFO) << "create scanner for interface with index: "
            << (int)interface_index_;
  scanner_ = new ScannerImpl(interface_index_,
                             scan_capabilities_,
                             wiphy_features_,
                             this,
                             scan_utils_);
  // Need to set the interface up (especially in scan mode since wpa_supplicant
  // is not started)
  if_tool_->SetUpState(interface_name_.c_str(), true);
}

ClientInterfaceImpl::~ClientInterfaceImpl() {
  binder_->NotifyImplDead();
  scanner_->Invalidate();
  netlink_utils_->UnsubscribeFrameTxStatusEvent(interface_index_);
  netlink_utils_->UnsubscribeMlmeEvent(interface_index_);
  netlink_utils_->UnsubscribeChannelSwitchEvent(interface_index_);
  if_tool_->SetUpState(interface_name_.c_str(), false);
}

sp<android::net::wifi::nl80211::IClientInterface> ClientInterfaceImpl::GetBinder() const {
  return binder_;
}

void ClientInterfaceImpl::Dump(std::stringstream* ss) const {
  *ss << "------- Dump of client interface with index: "
      << interface_index_ << " and name: " << interface_name_
      << "-------" << endl;
  *ss << "Max number of ssids for single shot scan: "
      << static_cast<int>(scan_capabilities_.max_num_scan_ssids) << endl;
  *ss << "Max number of ssids for scheduled scan: "
      << static_cast<int>(scan_capabilities_.max_num_sched_scan_ssids) << endl;
  *ss << "Max number of match sets for scheduled scan: "
      << static_cast<int>(scan_capabilities_.max_match_sets) << endl;
  *ss << "Maximum number of scan plans: "
      << scan_capabilities_.max_num_scan_plans << endl;
  *ss << "Max scan plan interval in seconds: "
      << scan_capabilities_.max_scan_plan_interval << endl;
  *ss << "Max scan plan iterations: "
      << scan_capabilities_.max_scan_plan_iterations << endl;
  *ss << "Device supports random MAC for single shot scan: "
      << wiphy_features_.supports_random_mac_oneshot_scan << endl;
  *ss << "Device supports low span single shot scan: "
      << wiphy_features_.supports_low_span_oneshot_scan << endl;
  *ss << "Device supports low power single shot scan: "
      << wiphy_features_.supports_low_power_oneshot_scan << endl;
  *ss << "Device supports high accuracy single shot scan: "
      << wiphy_features_.supports_high_accuracy_oneshot_scan << endl;
  *ss << "Device supports random MAC for scheduled scan: "
      << wiphy_features_.supports_random_mac_sched_scan << endl;
  *ss << "Device supports sending management frames at specified MCS rate: "
      << wiphy_features_.supports_tx_mgmt_frame_mcs << endl;
  *ss << "------- Dump End -------" << endl;
}

bool ClientInterfaceImpl::GetPacketCounters(vector<int32_t>* out_packet_counters) {
  StationInfo station_info;
  if (!netlink_utils_->GetStationInfo(interface_index_,
                                      bssid_,
                                      &station_info)) {
    return false;
  }
  out_packet_counters->push_back(station_info.station_tx_packets);
  out_packet_counters->push_back(station_info.station_tx_failed);

  return true;
}

bool ClientInterfaceImpl::SignalPoll(vector<int32_t>* out_signal_poll_results) {
  if (!IsAssociated()) {
    LOG(INFO) << "Fail RSSI polling because wifi is not associated.";
    return false;
  }

  StationInfo station_info;
  if (!netlink_utils_->GetStationInfo(interface_index_,
                                      bssid_,
                                      &station_info)) {
    return false;
  }
  out_signal_poll_results->push_back(
      static_cast<int32_t>(station_info.current_rssi));
  // Convert from 100kbit/s to Mbps.
  out_signal_poll_results->push_back(
      static_cast<int32_t>(station_info.station_tx_bitrate/10));
  // Association frequency.
  out_signal_poll_results->push_back(
      static_cast<int32_t>(associate_freq_));
  // Convert from 100kbit/s to Mbps.
  out_signal_poll_results->push_back(
      static_cast<int32_t>(station_info.station_rx_bitrate/10));

  return true;
}

const std::array<uint8_t, ETH_ALEN>& ClientInterfaceImpl::GetMacAddress() {
  return interface_mac_addr_;
}

void ClientInterfaceImpl::UpdateBandInfo() {
  LOG(INFO) << "UpdateBandInfo";
  if (!netlink_utils_->GetWiphyInfo(wiphy_index_,
                               &band_info_,
                               &scan_capabilities_,
                               &wiphy_features_)) {
    LOG(ERROR) << "Failed to get wiphy info from kernel";
  }
}

const BandInfo& ClientInterfaceImpl::GetBandInfo() const {
  return band_info_;
}

bool ClientInterfaceImpl::RefreshAssociateFreq() {
  // wpa_supplicant fetches associate frequency using the latest scan result.
  // We should follow the same method here before we find a better solution.
  std::vector<NativeScanResult> scan_results;
  if (!scan_utils_->GetScanResult(interface_index_, &scan_results)) {
    return false;
  }
  for (auto& scan_result : scan_results) {
    if (scan_result.associated) {
      associate_freq_ = scan_result.frequency;
    }
  }
  return false;
}

bool ClientInterfaceImpl::OnChannelSwitchEvent(uint32_t frequency) {
  if(!frequency) {
    LOG(ERROR) << "Frequency value is null";
    return false;
  }
  LOG(INFO) << "New channel on frequency: " << frequency;
  associate_freq_ = frequency;
  return true;
}

bool ClientInterfaceImpl::IsAssociated() const {
  return is_associated_;
}

void ClientInterfaceImpl::SendMgmtFrame(const vector<uint8_t>& frame,
    const sp<ISendMgmtFrameEvent>& callback, int32_t mcs) {
  if (mcs >= 0 && !wiphy_features_.supports_tx_mgmt_frame_mcs) {
    callback->OnFailure(
        ISendMgmtFrameEvent::SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED);
    return;
  }

  uint64_t cookie;
  if (!netlink_utils_->SendMgmtFrame(interface_index_, frame, mcs, &cookie)) {
    callback->OnFailure(ISendMgmtFrameEvent::SEND_MGMT_FRAME_ERROR_UNKNOWN);
    return;
  }

  frame_tx_in_progress_ = true;
  frame_tx_status_cookie_ = cookie;
  nsecs_t start_time_ns = systemTime(SYSTEM_TIME_MONOTONIC);
  on_frame_tx_status_event_handler_ =
      [callback, start_time_ns](bool was_acked) {
        if (was_acked) {
          nsecs_t end_time_ns = systemTime(SYSTEM_TIME_MONOTONIC);
          int32_t elapsed_time_ms = static_cast<int32_t>(
              nanoseconds_to_milliseconds(end_time_ns - start_time_ns));
          callback->OnAck(elapsed_time_ms);
        } else {
          callback->OnFailure(
              ISendMgmtFrameEvent::SEND_MGMT_FRAME_ERROR_NO_ACK);
        }
      };
}

}  // namespace wificond
}  // namespace android
