/*
 * 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/server.h"

#include <sstream>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/strings.h>
#include <binder/IPCThreadState.h>
#include <binder/PermissionCache.h>

#include "wificond/logging_utils.h"
#include "wificond/net/netlink_utils.h"
#include "wificond/scanning/scan_utils.h"

using android::base::WriteStringToFd;
using android::binder::Status;
using android::sp;
using android::IBinder;
using android::net::wifi::IApInterface;
using android::net::wifi::IClientInterface;
using android::net::wifi::IInterfaceEventCallback;
using android::wifi_system::HostapdManager;
using android::wifi_system::InterfaceTool;
using android::wifi_system::SupplicantManager;

using std::endl;
using std::placeholders::_1;
using std::string;
using std::stringstream;
using std::unique_ptr;
using std::vector;

namespace android {
namespace wificond {

namespace {

constexpr const char* kPermissionDump = "android.permission.DUMP";

}  // namespace

Server::Server(unique_ptr<InterfaceTool> if_tool,
               unique_ptr<SupplicantManager> supplicant_manager,
               unique_ptr<HostapdManager> hostapd_manager,
               NetlinkUtils* netlink_utils,
               ScanUtils* scan_utils)
    : if_tool_(std::move(if_tool)),
      supplicant_manager_(std::move(supplicant_manager)),
      hostapd_manager_(std::move(hostapd_manager)),
      netlink_utils_(netlink_utils),
      scan_utils_(scan_utils) {
}

Status Server::RegisterCallback(const sp<IInterfaceEventCallback>& callback) {
  for (auto& it : interface_event_callbacks_) {
    if (IInterface::asBinder(callback) == IInterface::asBinder(it)) {
      LOG(WARNING) << "Ignore duplicate interface event callback registration";
      return Status::ok();
    }
  }
  LOG(INFO) << "New interface event callback registered";
  interface_event_callbacks_.push_back(callback);
  return Status::ok();
}

Status Server::UnregisterCallback(const sp<IInterfaceEventCallback>& callback) {
  for (auto it = interface_event_callbacks_.begin();
       it != interface_event_callbacks_.end();
       it++) {
    if (IInterface::asBinder(callback) == IInterface::asBinder(*it)) {
      interface_event_callbacks_.erase(it);
      LOG(INFO) << "Unregister interface event callback";
      return Status::ok();
    }
  }
  LOG(WARNING) << "Failed to find registered interface event callback"
               << " to unregister";
  return Status::ok();
}

Status Server::createApInterface(const std::string& iface_name,
                                 sp<IApInterface>* created_interface) {
  InterfaceInfo interface;
  if (!SetupInterface(iface_name, &interface)) {
    return Status::ok();  // Logging was done internally
  }

  unique_ptr<ApInterfaceImpl> ap_interface(new ApInterfaceImpl(
      interface.name,
      interface.index,
      netlink_utils_,
      if_tool_.get(),
      hostapd_manager_.get()));
  *created_interface = ap_interface->GetBinder();
  BroadcastApInterfaceReady(ap_interface->GetBinder());
  ap_interfaces_[iface_name] = std::move(ap_interface);

  return Status::ok();
}

Status Server::tearDownApInterface(const std::string& iface_name,
                                   bool* out_success) {
  *out_success = false;
  const auto iter = ap_interfaces_.find(iface_name);
  if (iter != ap_interfaces_.end()) {
    BroadcastApInterfaceTornDown(iter->second->GetBinder());
    ap_interfaces_.erase(iter);
    *out_success = true;
  }
  return Status::ok();
}

Status Server::createClientInterface(const std::string& iface_name,
                                     sp<IClientInterface>* created_interface) {
  InterfaceInfo interface;
  if (!SetupInterface(iface_name, &interface)) {
    return Status::ok();  // Logging was done internally
  }

  unique_ptr<ClientInterfaceImpl> client_interface(new ClientInterfaceImpl(
      wiphy_index_,
      interface.name,
      interface.index,
      interface.mac_address,
      if_tool_.get(),
      netlink_utils_,
      scan_utils_));
  *created_interface = client_interface->GetBinder();
  BroadcastClientInterfaceReady(client_interface->GetBinder());
  client_interfaces_[iface_name] = std::move(client_interface);

  return Status::ok();
}

Status Server::tearDownClientInterface(const std::string& iface_name,
                                       bool* out_success) {
  *out_success = false;
  const auto iter = client_interfaces_.find(iface_name);
  if (iter != client_interfaces_.end()) {
    BroadcastClientInterfaceTornDown(iter->second->GetBinder());
    client_interfaces_.erase(iter);
    *out_success = true;
  }
  return Status::ok();
}

Status Server::tearDownInterfaces() {
  for (auto& it : client_interfaces_) {
    BroadcastClientInterfaceTornDown(it.second->GetBinder());
  }
  client_interfaces_.clear();

  for (auto& it : ap_interfaces_) {
    BroadcastApInterfaceTornDown(it.second->GetBinder());
  }
  ap_interfaces_.clear();

  MarkDownAllInterfaces();

  netlink_utils_->UnsubscribeRegDomainChange(wiphy_index_);

  return Status::ok();
}

Status Server::enableSupplicant(bool* success) {
  *success = supplicant_manager_->StartSupplicant();
  return Status::ok();
}

Status Server::disableSupplicant(bool* success) {
  *success = supplicant_manager_->StopSupplicant();
  return Status::ok();
}

Status Server::GetClientInterfaces(vector<sp<IBinder>>* out_client_interfaces) {
  vector<sp<android::IBinder>> client_interfaces_binder;
  for (auto& it : client_interfaces_) {
    out_client_interfaces->push_back(asBinder(it.second->GetBinder()));
  }
  return binder::Status::ok();
}

Status Server::GetApInterfaces(vector<sp<IBinder>>* out_ap_interfaces) {
  vector<sp<IBinder>> ap_interfaces_binder;
  for (auto& it : ap_interfaces_) {
    out_ap_interfaces->push_back(asBinder(it.second->GetBinder()));
  }
  return binder::Status::ok();
}

status_t Server::dump(int fd, const Vector<String16>& /*args*/) {
  if (!PermissionCache::checkCallingPermission(String16(kPermissionDump))) {
    IPCThreadState* ipc = android::IPCThreadState::self();
    LOG(ERROR) << "Caller (uid: " << ipc->getCallingUid()
               << ") is not permitted to dump wificond state";
    return PERMISSION_DENIED;
  }

  stringstream ss;
  ss << "Current wiphy index: " << wiphy_index_ << endl;
  ss << "Cached interfaces list from kernel message: " << endl;
  for (const auto& iface : interfaces_) {
    ss << "Interface index: " << iface.index
       << ", name: " << iface.name
       << ", mac address: "
       << LoggingUtils::GetMacString(iface.mac_address) << endl;
  }

  string country_code;
  if (netlink_utils_->GetCountryCode(&country_code)) {
    ss << "Current country code from kernel: " << country_code << endl;
  } else {
    ss << "Failed to get country code from kernel." << endl;
  }

  for (const auto& iface : client_interfaces_) {
    iface.second->Dump(&ss);
  }

  for (const auto& iface : ap_interfaces_) {
    iface.second->Dump(&ss);
  }

  if (!WriteStringToFd(ss.str(), fd)) {
    PLOG(ERROR) << "Failed to dump state to fd " << fd;
    return FAILED_TRANSACTION;
  }

  return OK;
}

void Server::MarkDownAllInterfaces() {
  uint32_t wiphy_index;
  vector<InterfaceInfo> interfaces;
  if (netlink_utils_->GetWiphyIndex(&wiphy_index) &&
      netlink_utils_->GetInterfaces(wiphy_index, &interfaces)) {
    for (InterfaceInfo& interface : interfaces) {
      if_tool_->SetUpState(interface.name.c_str(), false);
    }
  }
}

Status Server::getAvailable2gChannels(
    std::unique_ptr<vector<int32_t>>* out_frequencies) {
  BandInfo band_info;
  ScanCapabilities scan_capabilities_ignored;
  WiphyFeatures wiphy_features_ignored;

  if (!netlink_utils_->GetWiphyInfo(wiphy_index_, &band_info,
                                    &scan_capabilities_ignored,
                                    &wiphy_features_ignored)) {
    LOG(ERROR) << "Failed to get wiphy info from kernel";
    out_frequencies->reset(nullptr);
    return Status::ok();
  }

  out_frequencies->reset(
      new vector<int32_t>(band_info.band_2g.begin(), band_info.band_2g.end()));
  return Status::ok();
}

Status Server::getAvailable5gNonDFSChannels(
    std::unique_ptr<vector<int32_t>>* out_frequencies) {
  BandInfo band_info;
  ScanCapabilities scan_capabilities_ignored;
  WiphyFeatures wiphy_features_ignored;

  if (!netlink_utils_->GetWiphyInfo(wiphy_index_, &band_info,
                                    &scan_capabilities_ignored,
                                    &wiphy_features_ignored)) {
    LOG(ERROR) << "Failed to get wiphy info from kernel";
    out_frequencies->reset(nullptr);
    return Status::ok();
  }

  out_frequencies->reset(
      new vector<int32_t>(band_info.band_5g.begin(), band_info.band_5g.end()));
  return Status::ok();
}

Status Server::getAvailableDFSChannels(
    std::unique_ptr<vector<int32_t>>* out_frequencies) {
  BandInfo band_info;
  ScanCapabilities scan_capabilities_ignored;
  WiphyFeatures wiphy_features_ignored;

  if (!netlink_utils_->GetWiphyInfo(wiphy_index_, &band_info,
                                    &scan_capabilities_ignored,
                                    &wiphy_features_ignored)) {
    LOG(ERROR) << "Failed to get wiphy info from kernel";
    out_frequencies->reset(nullptr);
    return Status::ok();
  }

  out_frequencies->reset(new vector<int32_t>(band_info.band_dfs.begin(),
                                             band_info.band_dfs.end()));
  return Status::ok();
}

bool Server::SetupInterface(const std::string& iface_name,
                            InterfaceInfo* interface) {
  if (!RefreshWiphyIndex()) {
    return false;
  }

  netlink_utils_->SubscribeRegDomainChange(
          wiphy_index_,
          std::bind(&Server::OnRegDomainChanged,
          this,
          _1));

  interfaces_.clear();
  if (!netlink_utils_->GetInterfaces(wiphy_index_, &interfaces_)) {
    LOG(ERROR) << "Failed to get interfaces info from kernel";
    return false;
  }

  for (const auto& iface : interfaces_) {
    if (iface.name == iface_name) {
      *interface = iface;
      return true;
    }
  }

  LOG(ERROR) << "No usable interface found";
  return false;
}

bool Server::RefreshWiphyIndex() {
  if (!netlink_utils_->GetWiphyIndex(&wiphy_index_)) {
    LOG(ERROR) << "Failed to get wiphy index";
    return false;
  }
  return true;
}

void Server::OnRegDomainChanged(std::string& country_code) {
  if (country_code.empty()) {
    LOG(INFO) << "Regulatory domain changed";
  } else {
    LOG(INFO) << "Regulatory domain changed to country: " << country_code;
  }
  LogSupportedBands();
}

void Server::LogSupportedBands() {
  BandInfo band_info;
  ScanCapabilities scan_capabilities;
  WiphyFeatures wiphy_features;
  netlink_utils_->GetWiphyInfo(wiphy_index_,
                               &band_info,
                               &scan_capabilities,
                               &wiphy_features);

  stringstream ss;
  for (unsigned int i = 0; i < band_info.band_2g.size(); i++) {
    ss << " " << band_info.band_2g[i];
  }
  LOG(INFO) << "2.4Ghz frequencies:"<< ss.str();
  ss.str("");

  for (unsigned int i = 0; i < band_info.band_5g.size(); i++) {
    ss << " " << band_info.band_5g[i];
  }
  LOG(INFO) << "5Ghz non-DFS frequencies:"<< ss.str();
  ss.str("");

  for (unsigned int i = 0; i < band_info.band_dfs.size(); i++) {
    ss << " " << band_info.band_dfs[i];
  }
  LOG(INFO) << "5Ghz DFS frequencies:"<< ss.str();
}

void Server::BroadcastClientInterfaceReady(
    sp<IClientInterface> network_interface) {
  for (auto& it : interface_event_callbacks_) {
    it->OnClientInterfaceReady(network_interface);
  }
}

void Server::BroadcastApInterfaceReady(
    sp<IApInterface> network_interface) {
  for (auto& it : interface_event_callbacks_) {
    it->OnApInterfaceReady(network_interface);
  }
}

void Server::BroadcastClientInterfaceTornDown(
    sp<IClientInterface> network_interface) {
  for (auto& it : interface_event_callbacks_) {
    it->OnClientTorndownEvent(network_interface);
  }
}

void Server::BroadcastApInterfaceTornDown(
    sp<IApInterface> network_interface) {
  for (auto& it : interface_event_callbacks_) {
    it->OnApTorndownEvent(network_interface);
  }
}

}  // namespace wificond
}  // namespace android
