// Copyright 2017 The Fuchsia 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 <wlan/mlme/ap/ap_mlme.h>
#include <wlan/mlme/service.h>

#include <wlan/common/logging.h>
#include <wlan/protocol/mac.h>

#include <zircon/status.h>

namespace wlan {

namespace wlan_mlme = ::fuchsia::wlan::mlme;

ApMlme::ApMlme(DeviceInterface* device) : device_(device) {}

ApMlme::~ApMlme() {
    // Ensure the BSS is correctly stopped and terminated when destroying the
    // MLME.
    if (bss_ != nullptr && bss_->IsStarted()) { bss_->Stop(); }
}

zx_status_t ApMlme::Init() {
    debugfn();
    return ZX_OK;
}

zx_status_t ApMlme::HandleTimeout(const ObjectId id) {
    debugfn();

    switch (id.target()) {
    case to_enum_type(ObjectTarget::kBss): {
        return bss_->HandleTimeout();
    }
    default:
        ZX_DEBUG_ASSERT(false);
        break;
    }

    return ZX_OK;
}

zx_status_t ApMlme::HandleMlmeMsg(const BaseMlmeMsg& msg) {
    if (auto start_req = msg.As<wlan_mlme::StartRequest>()) {
        return HandleMlmeStartReq(*start_req);
    } else if (auto stop_req = msg.As<wlan_mlme::StopRequest>()) {
        return HandleMlmeStopReq(*stop_req);
    }
    return bss_->HandleMlmeMsg(msg);
}

zx_status_t ApMlme::HandleFramePacket(fbl::unique_ptr<Packet> pkt) {
    if (bss_ != nullptr) { bss_->HandleAnyFrame(std::move(pkt)); }
    return ZX_OK;
}

zx_status_t ApMlme::HandleMlmeStartReq(const MlmeMsg<wlan_mlme::StartRequest>& req) {
    debugfn();

    // Only one BSS can be started at a time.
    if (bss_ != nullptr) {
        debugf("BSS %s already running but received MLME-START.request\n",
               device_->GetState()->address().ToString().c_str());
        return service::SendStartConfirm(
            device_, wlan_mlme::StartResultCodes::BSS_ALREADY_STARTED_OR_JOINED);
    }

    ObjectId timer_id;
    timer_id.set_subtype(to_enum_type(ObjectSubtype::kTimer));
    timer_id.set_target(to_enum_type(ObjectTarget::kBss));
    fbl::unique_ptr<Timer> timer;
    zx_status_t status = device_->GetTimer(ToPortKey(PortKeyType::kMlme, timer_id.val()), &timer);
    if (status != ZX_OK) {
        errorf("Could not create bss timer: %s\n", zx_status_get_string(status));
        return service::SendStartConfirm(device_, wlan_mlme::StartResultCodes::INTERNAL_ERROR);
    }

    // Configure BSS in driver.
    auto& bssid = device_->GetState()->address();
    wlan_bss_config_t cfg{
        .bss_type = WLAN_BSS_TYPE_INFRASTRUCTURE,
        .remote = false,
    };
    bssid.CopyTo(cfg.bssid);
    device_->ConfigureBss(&cfg);

    // Create and start BSS.
    auto bcn_sender = fbl::make_unique<BeaconSender>(device_);
    bss_.reset(new InfraBss(device_, std::move(bcn_sender), bssid, std::move(timer)));
    bss_->Start(req);

    return service::SendStartConfirm(device_, wlan_mlme::StartResultCodes::SUCCESS);
}

zx_status_t ApMlme::HandleMlmeStopReq(const MlmeMsg<wlan_mlme::StopRequest>& req) {
    debugfn();

    if (bss_ == nullptr) {
        errorf("received MLME-STOP.request but no BSS is running on device: %s\n",
               device_->GetState()->address().ToString().c_str());
        return ZX_OK;
    }

    // Stop and destroy BSS.
    bss_->Stop();
    bss_.reset();

    return ZX_OK;
}

void ApMlme::HwIndication(uint32_t ind) {
    if (ind == WLAN_INDICATION_PRE_TBTT) {
        bss_->OnPreTbtt();
    } else if (ind == WLAN_INDICATION_BCN_TX_COMPLETE) {
        bss_->OnBcnTxComplete();
    }
}

HtConfig ApMlme::Ht() const {
    return bss_->Ht();
}

const Span<const SupportedRate> ApMlme::Rates() const {
    return bss_->Rates();
}

}  // namespace wlan
