/*
 *
 *    Copyright (c) 2021-2022 Project CHIP Authors
 *
 *    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.
 */

/**
 *    @file
 *          Provides an implementation of the DiagnosticDataProvider object
 *          for P6 platform.
 */

#include <platform/internal/CHIPDeviceLayerInternal.h>

#include "cyhal_system.h"
#include <cy_lwip.h>
#include <lib/support/CHIPMemString.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/DiagnosticDataProvider.h>
#include <platform/Infineon/PSOC6/DiagnosticDataProviderImpl.h>
#include <platform/Infineon/PSOC6/P6Utils.h>

namespace chip {
namespace DeviceLayer {

DiagnosticDataProviderImpl & DiagnosticDataProviderImpl::GetDefaultInstance()
{
    static DiagnosticDataProviderImpl sInstance;
    return sInstance;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetCurrentHeapFree(uint64_t & currentHeapFree)
{
    heap_info_t heap;
    Internal::P6Utils::heap_usage(&heap);
    currentHeapFree = static_cast<uint64_t>(heap.HeapFree);
    return CHIP_NO_ERROR;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetCurrentHeapUsed(uint64_t & currentHeapUsed)
{
    // Calculate the Heap used based on Total heap - Free heap
    heap_info_t heap;
    Internal::P6Utils::heap_usage(&heap);
    currentHeapUsed = static_cast<uint64_t>(heap.HeapUsed);
    return CHIP_NO_ERROR;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetCurrentHeapHighWatermark(uint64_t & currentHeapHighWatermark)
{
    heap_info_t heap;
    Internal::P6Utils::heap_usage(&heap);
    currentHeapHighWatermark = static_cast<uint64_t>(heap.HeapMax);
    return CHIP_NO_ERROR;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetRebootCount(uint16_t & rebootCount)
{
    uint32_t count = 0;

    CHIP_ERROR err = ConfigurationMgr().GetRebootCount(count);

    if (err == CHIP_NO_ERROR)
    {
        VerifyOrReturnError(count <= UINT16_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);
        rebootCount = static_cast<uint16_t>(count);
    }

    return err;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetUpTime(uint64_t & upTime)
{
    System::Clock::Timestamp currentTime = System::SystemClock().GetMonotonicTimestamp();
    System::Clock::Timestamp startTime   = PlatformMgrImpl().GetStartTime();

    if (currentTime >= startTime)
    {
        upTime = std::chrono::duration_cast<System::Clock::Seconds64>(currentTime - startTime).count();
        return CHIP_NO_ERROR;
    }

    return CHIP_ERROR_INVALID_TIME;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetTotalOperationalHours(uint32_t & totalOperationalHours)
{
    uint64_t upTime = 0;

    if (GetUpTime(upTime) == CHIP_NO_ERROR)
    {
        uint32_t totalHours = 0;
        if (ConfigurationMgr().GetTotalOperationalHours(totalHours) == CHIP_NO_ERROR)
        {
            /* uptime is terms of seconds and dividing it by 3600 to calculate
             * totalOperationalHours in hours.
             */
            VerifyOrReturnError(upTime / 3600 <= UINT32_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);
            totalOperationalHours = totalHours + static_cast<uint32_t>(upTime / 3600);
            return CHIP_NO_ERROR;
        }
    }

    return CHIP_ERROR_INVALID_TIME;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetBootReason(BootReasonType & bootReason)
{
    cyhal_reset_reason_t reset_reason = cyhal_system_get_reset_reason();
    if (reset_reason == CYHAL_SYSTEM_RESET_NONE)
    {
        bootReason = BootReasonType::kPowerOnReboot;
    }
    else if (reset_reason == CYHAL_SYSTEM_RESET_WDT)
    {
        bootReason = BootReasonType::kSoftwareWatchdogReset;
    }
    else if (reset_reason == CYHAL_SYSTEM_RESET_SOFT)
    {
        bootReason = BootReasonType::kSoftwareReset;
    }
    else if (reset_reason == CYHAL_SYSTEM_RESET_HIB_WAKEUP)
    {
        bootReason = BootReasonType::kHardwareWatchdogReset;
    }
    else
    {
        bootReason = BootReasonType::kUnspecified;
    }
    return CHIP_NO_ERROR;
}

void DiagnosticDataProviderImpl::UpdateoffPremiseService(bool ipv4service, bool ipv6service)
{
    /* Enable/Disable IPv4 Off Premise Services */
    mipv4_offpremise.SetNonNull(ipv4service);

    /* Enable/Disable IPv6 Off Premise Services */
    mipv6_offpremise.SetNonNull(ipv6service);
}

CHIP_ERROR DiagnosticDataProviderImpl::GetNetworkInterfaces(NetworkInterface ** netifpp)
{
    struct netif * net_interface;
    CHIP_ERROR err         = CHIP_NO_ERROR;
    NetworkInterface * ifp = new NetworkInterface();
    net_interface          = cy_lwip_get_interface(CY_LWIP_STA_NW_INTERFACE);
    if (net_interface)
    {
        /* Update Network Interface list */
        ifp->name                            = CharSpan::fromCharString(net_interface->name);
        ifp->isOperational                   = net_interface->flags & NETIF_FLAG_LINK_UP;
        ifp->type                            = EMBER_ZCL_INTERFACE_TYPE_WI_FI;
        ifp->offPremiseServicesReachableIPv4 = mipv4_offpremise;
        ifp->offPremiseServicesReachableIPv6 = mipv6_offpremise;
        ifp->hardwareAddress                 = ByteSpan(net_interface->hwaddr, net_interface->hwaddr_len);
    }
    *netifpp = ifp;

    return err;
}

void DiagnosticDataProviderImpl::ReleaseNetworkInterfaces(NetworkInterface * netifp)
{
    while (netifp)
    {
        NetworkInterface * del = netifp;
        netifp                 = netifp->Next;
        delete del;
    }
}

/* Wi-Fi Diagnostics Cluster Support */

CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiBssId(ByteSpan & value)
{
    cy_wcm_associated_ap_info_t ap_info;
    cy_rslt_t result = CY_RSLT_SUCCESS;
    CHIP_ERROR err   = CHIP_NO_ERROR;
    ChipLogError(DeviceLayer, "cy_wcm_get_associated_ap_info\r\n");
    result = cy_wcm_get_associated_ap_info(&ap_info);
    if (result != CY_RSLT_SUCCESS)
    {
        ChipLogError(DeviceLayer, "cy_wcm_get_associated_ap_info failed: %d", (int) result);
        SuccessOrExit(CHIP_ERROR_INTERNAL);
    }
    memcpy(mWiFiMacAddress, ap_info.BSSID, CY_WCM_MAC_ADDR_LEN);
    value = ByteSpan(mWiFiMacAddress, CY_WCM_MAC_ADDR_LEN);

exit:
    return err;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiSecurityType(uint8_t & securityType)
{
    cy_wcm_associated_ap_info_t ap_info;
    cy_rslt_t result = CY_RSLT_SUCCESS;
    CHIP_ERROR err   = CHIP_NO_ERROR;

    result = cy_wcm_get_associated_ap_info(&ap_info);
    if (result != CY_RSLT_SUCCESS)
    {
        ChipLogError(DeviceLayer, "cy_wcm_get_associated_ap_info failed: %d", (int) result);
        SuccessOrExit(CHIP_ERROR_INTERNAL);
    }
    if (ap_info.security == CY_WCM_SECURITY_OPEN)
    {
        securityType = EMBER_ZCL_SECURITY_TYPE_NONE;
    }
    else if (ap_info.security & WPA3_SECURITY)
    {
        securityType = EMBER_ZCL_SECURITY_TYPE_WPA3;
    }
    else if (ap_info.security & WPA2_SECURITY)
    {
        securityType = EMBER_ZCL_SECURITY_TYPE_WPA2;
    }
    else if (ap_info.security & WPA_SECURITY)
    {
        securityType = EMBER_ZCL_SECURITY_TYPE_WPA;
    }
    else if (ap_info.security & WEP_ENABLED)
    {
        securityType = EMBER_ZCL_SECURITY_TYPE_WEP;
    }
    else
    {
        securityType = EMBER_ZCL_SECURITY_TYPE_UNSPECIFIED;
    }

exit:
    return err;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiVersion(uint8_t & wiFiVersion)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    wl_bss_info_t bss_info;
    whd_security_t security;
    cy_rslt_t result = CY_RSLT_SUCCESS;

    result = whd_wifi_get_ap_info(whd_ifs[CY_WCM_INTERFACE_TYPE_STA], &bss_info, &security);
    if (result != CY_RSLT_SUCCESS)
    {
        ChipLogError(DeviceLayer, "whd_wifi_get_ap_info failed: %d", (int) result);
        SuccessOrExit(CHIP_ERROR_INTERNAL);
    }

    /* VHT Capable */
    if (bss_info.vht_cap)
    {
        wiFiVersion = EMBER_ZCL_WI_FI_VERSION_TYPE_802__11AC;
    }
    /* HT Capable */
    else if (bss_info.n_cap)
    {
        wiFiVersion = EMBER_ZCL_WI_FI_VERSION_TYPE_802__11N;
    }
    /* 11g Capable */
    else
    {
        wiFiVersion = EMBER_ZCL_WI_FI_VERSION_TYPE_802__11G;
    }

exit:
    return err;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiChannelNumber(uint16_t & channelNumber)
{
    cy_wcm_associated_ap_info_t ap_info;
    cy_rslt_t result = CY_RSLT_SUCCESS;
    CHIP_ERROR err   = CHIP_NO_ERROR;

    result = cy_wcm_get_associated_ap_info(&ap_info);
    if (result != CY_RSLT_SUCCESS)
    {
        ChipLogError(DeviceLayer, "cy_wcm_get_associated_ap_info failed: %d", (int) result);
        SuccessOrExit(CHIP_ERROR_INTERNAL);
    }
    channelNumber = ap_info.channel;

exit:
    return err;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiRssi(int8_t & rssi)
{
    cy_wcm_associated_ap_info_t ap_info;
    cy_rslt_t result = CY_RSLT_SUCCESS;
    CHIP_ERROR err   = CHIP_NO_ERROR;

    result = cy_wcm_get_associated_ap_info(&ap_info);
    if (result != CY_RSLT_SUCCESS)
    {
        ChipLogError(DeviceLayer, "cy_wcm_get_associated_ap_info failed: %d", (int) result);
        SuccessOrExit(CHIP_ERROR_INTERNAL);
    }
    rssi = ap_info.signal_strength;

exit:
    return err;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiBeaconRxCount(uint32_t & beaconRxCount)
{
    uint64_t count;
    ReturnErrorOnFailure(WiFiCounters(WiFiStatsCountType::kWiFiBeaconRxCount, count));

    count -= mBeaconRxCount;
    VerifyOrReturnError(count <= UINT32_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);
    beaconRxCount = static_cast<uint32_t>(count);

    return CHIP_NO_ERROR;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiBeaconLostCount(uint32_t & beaconLostCount)
{
    uint64_t count;
    ReturnErrorOnFailure(WiFiCounters(WiFiStatsCountType::kWiFiBeaconLostCount, count));

    count -= mBeaconLostCount;
    VerifyOrReturnError(count <= UINT32_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);
    beaconLostCount = static_cast<uint32_t>(count);

    return CHIP_NO_ERROR;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiCurrentMaxRate(uint64_t & currentMaxRate)
{
    cy_rslt_t result = CY_RSLT_SUCCESS;
    cy_wcm_wlan_statistics_t stats;
    CHIP_ERROR err = CHIP_NO_ERROR;
    uint64_t count;

    result = cy_wcm_get_wlan_statistics(CY_WCM_INTERFACE_TYPE_STA, &stats);
    if (result != CY_RSLT_SUCCESS)
    {
        ChipLogError(DeviceLayer, "cy_wcm_get_wlan_statistics failed: %d", (int) result);
        SuccessOrExit(CHIP_ERROR_INTERNAL);
    }
    count          = stats.tx_bitrate * PHYRATE_KPBS_BYTES_PER_SEC;
    currentMaxRate = static_cast<uint32_t>(count);

exit:
    return err;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketMulticastRxCount(uint32_t & packetMulticastRxCount)
{
    uint64_t count;
    ReturnErrorOnFailure(WiFiCounters(WiFiStatsCountType::kWiFiMulticastPacketRxCount, count));

    count -= mPacketMulticastRxCount;
    VerifyOrReturnError(count <= UINT32_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);
    packetMulticastRxCount = static_cast<uint32_t>(count);

    return CHIP_NO_ERROR;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketMulticastTxCount(uint32_t & packetMulticastTxCount)
{
    uint64_t count;
    ReturnErrorOnFailure(WiFiCounters(WiFiStatsCountType::kWiFiMulticastPacketTxCount, count));

    count -= mPacketMulticastTxCount;
    VerifyOrReturnError(count <= UINT32_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);
    packetMulticastTxCount = static_cast<uint32_t>(count);

    return CHIP_NO_ERROR;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketUnicastRxCount(uint32_t & packetUnicastRxCount)
{
    cy_rslt_t result = CY_RSLT_SUCCESS;
    cy_wcm_wlan_statistics_t stats;
    CHIP_ERROR err = CHIP_NO_ERROR;
    uint64_t count;

    result = cy_wcm_get_wlan_statistics(CY_WCM_INTERFACE_TYPE_STA, &stats);
    if (result != CY_RSLT_SUCCESS)
    {
        ChipLogError(DeviceLayer, "cy_wcm_get_wlan_statistics failed: %d", (int) result);
        SuccessOrExit(CHIP_ERROR_INTERNAL);
    }
    count = stats.rx_packets;
    count -= mPacketUnicastRxCount;
    VerifyOrReturnError(count <= UINT32_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);

    packetUnicastRxCount = static_cast<uint32_t>(count);

exit:
    return err;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketUnicastTxCount(uint32_t & packetUnicastTxCount)
{
    cy_rslt_t result = CY_RSLT_SUCCESS;
    cy_wcm_wlan_statistics_t stats;
    CHIP_ERROR err = CHIP_NO_ERROR;
    uint64_t count;

    result = cy_wcm_get_wlan_statistics(CY_WCM_INTERFACE_TYPE_STA, &stats);
    if (result != CY_RSLT_SUCCESS)
    {
        ChipLogError(DeviceLayer, "cy_wcm_get_wlan_statistics failed: %d", (int) result);
        SuccessOrExit(CHIP_ERROR_INTERNAL);
    }

    count = stats.tx_packets;
    count -= mPacketUnicastTxCount;
    VerifyOrReturnError(count <= UINT32_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);

    packetUnicastTxCount = static_cast<uint32_t>(count);

exit:
    return err;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiOverrunCount(uint64_t & overrunCount)
{
    uint64_t count;
    ReturnErrorOnFailure(WiFiCounters(WiFiStatsCountType::kWiFiOverrunCount, count));

    count -= mOverrunCount;
    VerifyOrReturnError(count <= UINT32_MAX, CHIP_ERROR_INVALID_INTEGER_VALUE);
    overrunCount = static_cast<uint32_t>(count);

    return CHIP_NO_ERROR;
}

CHIP_ERROR DiagnosticDataProviderImpl::ResetWiFiNetworkDiagnosticsCounts()
{
    uint64_t count;
    return WiFiCounters(WiFiStatsCountType::kWiFiResetCount, count);
}

void DiagnosticDataProviderImpl::ReadCounters(WiFiStatsCountType Counttype, uint64_t & count, wl_cnt_ver_30_t * cnt,
                                              wl_cnt_ge40mcst_v1_t * cnt_ge40)
{
    if ((!cnt) || (!cnt_ge40))
    {
        ChipLogError(DeviceLayer, "ReadCounters failed due to NULL Pointers passed");
        return;
    }
    /* Populate count based in the Counttype */
    switch (Counttype)
    {
    case WiFiStatsCountType::kWiFiUnicastPacketRxCount:
        count = cnt->rxfrag;
        break;
    case WiFiStatsCountType::kWiFiUnicastPacketTxCount:
        count = cnt->txfrag;
        break;
    case WiFiStatsCountType::kWiFiMulticastPacketRxCount:
        count = cnt->rxmulti;
        break;
    case WiFiStatsCountType::kWiFiMulticastPacketTxCount:
        count = cnt->txmulti;
        break;
    case WiFiStatsCountType::kWiFiOverrunCount:
        count = cnt->txnobuf + cnt->rxnobuf;
        break;
    case WiFiStatsCountType::kWiFiBeaconLostCount:
        count = cnt_ge40->missbcn_dbg;
        break;
    case WiFiStatsCountType::kWiFiBeaconRxCount:
        count = cnt_ge40->rxbeaconmbss;
        break;
    /* Update below variables during reset counts command so that next count read will be
     *  starting from these values.
     */
    case WiFiStatsCountType::kWiFiResetCount:
        mBeaconRxCount          = cnt_ge40->rxbeaconmbss;
        mBeaconLostCount        = cnt_ge40->missbcn_dbg;
        mPacketMulticastRxCount = cnt->rxmulti;
        mPacketMulticastTxCount = cnt->txmulti;
        mPacketUnicastRxCount   = cnt->rxfrag;
        mPacketUnicastTxCount   = cnt->txfrag;
        mOverrunCount           = cnt->txnobuf + cnt->rxnobuf;
        break;
    default:
        ChipLogError(DeviceLayer, "ReadCounters type not handled : %d", (int) Counttype);
        break;
    }
}
void DiagnosticDataProviderImpl::xtlv_buffer_parsing(const uint8_t * tlv_buf, uint16_t buflen, WiFiStatsCountType Counttype,
                                                     uint64_t & count)
{
    wl_cnt_ver_30_t cnt;
    wl_cnt_ge40mcst_v1_t cnt_ge40;

    /* parse the tlv buffer and populate the cnt and cnt_ge40 buffer with the counter values */
    Internal::P6Utils::unpack_xtlv_buf(tlv_buf, buflen, &cnt, &cnt_ge40);

    /* Read the counter based on the Counttype passed */
    ReadCounters(Counttype, count, &cnt, &cnt_ge40);
    return;
}

CHIP_ERROR DiagnosticDataProviderImpl::WiFiCounters(WiFiStatsCountType type, uint64_t & count)
{
    whd_buffer_t buffer;
    whd_buffer_t response;
    wl_cnt_info_t * wl_cnt_info = NULL;
    CHIP_ERROR err              = CHIP_NO_ERROR;

    /* Read wl counters iovar using WHD APIs */
    whd_cdc_get_iovar_buffer(whd_ifs[CY_WCM_INTERFACE_TYPE_STA]->whd_driver, &buffer, WLC_IOCTL_MEDLEN, IOVAR_STR_COUNTERS);
    whd_cdc_send_iovar(whd_ifs[CY_WCM_INTERFACE_TYPE_STA], CDC_GET, buffer, &response);
    wl_cnt_info =
        (wl_cnt_info_t *) whd_buffer_get_current_piece_data_pointer(whd_ifs[CY_WCM_INTERFACE_TYPE_STA]->whd_driver, response);

    /* Parse the buffer only for Counter Version 30 */
    if (wl_cnt_info->version == WL_CNT_VER_30)
    {
        /* 43012 board - Process xtlv buffer data to get statistics */
        uint8_t * cntdata;
        cntdata = (uint8_t *) malloc(wl_cnt_info->datalen);

        CHK_CNTBUF_DATALEN(wl_cnt_info, WLC_IOCTL_MEDLEN);
        if (cntdata == NULL)
        {
            return CHIP_ERROR_INTERNAL;
        }
        /* Allocate the memory for buffer */
        memcpy(cntdata, wl_cnt_info->data, wl_cnt_info->datalen);

        /* parse the xtlv wl counters data */
        xtlv_buffer_parsing(cntdata, wl_cnt_info->datalen, type, count);

        /* Free the memory */
        free(cntdata);
    }
    return err;
}

CHIP_ERROR DiagnosticDataProviderImpl::GetThreadMetrics(ThreadMetrics ** threadMetricsOut)
{
    /* Obtain all available task information */
    TaskStatus_t * taskStatusArray;
    ThreadMetrics * head = nullptr;
    unsigned long arraySize, x, dummy;
    arraySize = uxTaskGetNumberOfTasks();

    taskStatusArray = (TaskStatus_t *) pvPortMalloc(arraySize * sizeof(TaskStatus_t));

    if (taskStatusArray != NULL)
    {
        /* Generate raw status information about each task. */
        arraySize = uxTaskGetSystemState(taskStatusArray, arraySize, &dummy);
        /* For each populated position in the taskStatusArray array,
           format the raw data as human readable ASCII data. */

        for (x = 0; x < arraySize; x++)
        {
            ThreadMetrics * thread = (ThreadMetrics *) pvPortMalloc(sizeof(ThreadMetrics));

            Platform::CopyString(thread->NameBuf, taskStatusArray[x].pcTaskName);
            thread->name.Emplace(CharSpan::fromCharString(thread->NameBuf));
            thread->id = taskStatusArray[x].xTaskNumber;

            thread->stackFreeMinimum.Emplace(taskStatusArray[x].usStackHighWaterMark);
            /* Unsupported metrics */
            thread->stackSize.Emplace(0);
            thread->stackFreeCurrent.Emplace(0);

            thread->Next = head;
            head         = thread;
        }

        *threadMetricsOut = head;
        /* The array is no longer needed, free the memory it consumes. */
        vPortFree(taskStatusArray);
    }

    return CHIP_NO_ERROR;
}

void DiagnosticDataProviderImpl::ReleaseThreadMetrics(ThreadMetrics * threadMetrics)
{
    while (threadMetrics)
    {
        ThreadMetrics * del = threadMetrics;
        threadMetrics       = threadMetrics->Next;
        vPortFree(del);
    }
}

DiagnosticDataProvider & GetDiagnosticDataProviderImpl()
{
    return DiagnosticDataProviderImpl::GetDefaultInstance();
}

} // namespace DeviceLayer
} // namespace chip
