/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *    Copyright (c) 2018 Nest Labs, Inc.
 *    All rights reserved.
 *
 *    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
 *          General utility methods for the ESP32 platform.
 */
/* this file behaves like a config.h, comes first */
#include <platform/internal/CHIPDeviceLayerInternal.h>

#include <lib/support/CodeUtils.h>
#include <lib/support/ErrorStr.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/ESP32/ESP32Utils.h>

#include "esp_event.h"
#include "esp_netif.h"
#include "esp_netif_net_stack.h"
#include "esp_wifi.h"
#include "nvs.h"

using namespace ::chip::DeviceLayer::Internal;
using chip::DeviceLayer::Internal::DeviceNetworkInfo;

CHIP_ERROR ESP32Utils::IsAPEnabled(bool & apEnabled)
{
    wifi_mode_t curWiFiMode;

    esp_err_t err = esp_wifi_get_mode(&curWiFiMode);
    if (err != ESP_OK)
    {
        ChipLogError(DeviceLayer, "esp_wifi_get_mode() failed: %s", esp_err_to_name(err));
        return ESP32Utils::MapError(err);
    }

    apEnabled = (curWiFiMode == WIFI_MODE_AP || curWiFiMode == WIFI_MODE_APSTA);

    return CHIP_NO_ERROR;
}

CHIP_ERROR ESP32Utils::IsStationEnabled(bool & staEnabled)
{
    wifi_mode_t curWiFiMode;
    esp_err_t err = esp_wifi_get_mode(&curWiFiMode);
    if (err != ESP_OK)
    {
        ChipLogError(DeviceLayer, "esp_wifi_get_mode() failed: %s", esp_err_to_name(err));
        return ESP32Utils::MapError(err);
    }

    staEnabled = (curWiFiMode == WIFI_MODE_STA || curWiFiMode == WIFI_MODE_APSTA);

    return CHIP_NO_ERROR;
}

bool ESP32Utils::IsStationProvisioned(void)
{
    wifi_config_t stationConfig;
    return (esp_wifi_get_config(WIFI_IF_STA, &stationConfig) == ERR_OK && stationConfig.sta.ssid[0] != 0);
}

CHIP_ERROR ESP32Utils::IsStationConnected(bool & connected)
{
    wifi_ap_record_t apInfo;
    connected = (esp_wifi_sta_get_ap_info(&apInfo) == ESP_OK);
    return CHIP_NO_ERROR;
}

CHIP_ERROR ESP32Utils::StartWiFiLayer(void)
{
    int8_t ignored;
    bool wifiStarted;

    // There appears to be no direct way to ask the ESP WiFi layer if esp_wifi_start()
    // has been called.  So use the ESP_ERR_WIFI_NOT_STARTED error returned by
    // esp_wifi_get_max_tx_power() to detect this.
    esp_err_t err = esp_wifi_get_max_tx_power(&ignored);
    switch (err)
    {
    case ESP_OK:
        wifiStarted = true;
        break;
    case ESP_ERR_WIFI_NOT_STARTED:
        wifiStarted = false;
        break;
    default:
        return ESP32Utils::MapError(err);
    }

    if (!wifiStarted)
    {
        ChipLogProgress(DeviceLayer, "Starting ESP WiFi layer");

        err = esp_wifi_start();
        if (err != ESP_OK)
        {
            ChipLogError(DeviceLayer, "esp_wifi_start() failed: %s", esp_err_to_name(err));
            return ESP32Utils::MapError(err);
        }
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR ESP32Utils::EnableStationMode(void)
{
    wifi_mode_t curWiFiMode;

    // Get the current ESP WiFI mode.
    esp_err_t err = esp_wifi_get_mode(&curWiFiMode);
    if (err != ESP_OK)
    {
        ChipLogError(DeviceLayer, "esp_wifi_get_mode() failed: %s", esp_err_to_name(err));
        return ESP32Utils::MapError(err);
    }

    // If station mode is not already enabled (implying the current mode is WIFI_MODE_AP), change
    // the mode to WIFI_MODE_APSTA.
    if (curWiFiMode == WIFI_MODE_AP)
    {
        ChipLogProgress(DeviceLayer, "Changing ESP WiFi mode: %s -> %s", WiFiModeToStr(WIFI_MODE_AP),
                        WiFiModeToStr(WIFI_MODE_APSTA));

        err = esp_wifi_set_mode(WIFI_MODE_APSTA);
        if (err != ESP_OK)
        {
            ChipLogError(DeviceLayer, "esp_wifi_set_mode() failed: %s", esp_err_to_name(err));
            return ESP32Utils::MapError(err);
        }
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR ESP32Utils::SetAPMode(bool enabled)
{
    wifi_mode_t curWiFiMode, targetWiFiMode;

    targetWiFiMode = (enabled) ? WIFI_MODE_APSTA : WIFI_MODE_STA;

    // Get the current ESP WiFI mode.
    esp_err_t err = esp_wifi_get_mode(&curWiFiMode);
    if (err != ESP_OK)
    {
        ChipLogError(DeviceLayer, "esp_wifi_get_mode() failed: %s", esp_err_to_name(err));
        return ESP32Utils::MapError(err);
    }

    // If station mode is not already enabled (implying the current mode is WIFI_MODE_AP), change
    // the mode to WIFI_MODE_APSTA.
    if (curWiFiMode != targetWiFiMode)
    {
        ChipLogProgress(DeviceLayer, "Changing ESP WiFi mode: %s -> %s", WiFiModeToStr(curWiFiMode), WiFiModeToStr(targetWiFiMode));

        err = esp_wifi_set_mode(targetWiFiMode);
        if (err != ESP_OK)
        {
            ChipLogError(DeviceLayer, "esp_wifi_set_mode() failed: %s", esp_err_to_name(err));
            return ESP32Utils::MapError(err);
        }
    }

    return CHIP_NO_ERROR;
}

int ESP32Utils::OrderScanResultsByRSSI(const void * _res1, const void * _res2)
{
    const wifi_ap_record_t * res1 = (const wifi_ap_record_t *) _res1;
    const wifi_ap_record_t * res2 = (const wifi_ap_record_t *) _res2;

    if (res1->rssi > res2->rssi)
    {
        return -1;
    }
    if (res1->rssi < res2->rssi)
    {
        return 1;
    }
    return 0;
}

const char * ESP32Utils::WiFiModeToStr(wifi_mode_t wifiMode)
{
    switch (wifiMode)
    {
    case WIFI_MODE_NULL:
        return "NULL";
    case WIFI_MODE_STA:
        return "STA";
    case WIFI_MODE_AP:
        return "AP";
    case WIFI_MODE_APSTA:
        return "STA+AP";
    default:
        return "(unknown)";
    }
}

struct netif * ESP32Utils::GetStationNetif(void)
{
    return GetNetif("WIFI_STA_DEF");
}

struct netif * ESP32Utils::GetNetif(const char * ifKey)
{
    struct netif * netif       = NULL;
    esp_netif_t * netif_handle = NULL;
    netif_handle               = esp_netif_get_handle_from_ifkey(ifKey);
    netif                      = (struct netif *) esp_netif_get_netif_impl(netif_handle);
    return netif;
}

bool ESP32Utils::IsInterfaceUp(const char * ifKey)
{
    struct netif * netif = GetNetif(ifKey);
    return netif != NULL && netif_is_up(netif);
}

bool ESP32Utils::HasIPv6LinkLocalAddress(const char * ifKey)
{
    struct esp_ip6_addr if_ip6_unused;
    return esp_netif_get_ip6_linklocal(esp_netif_get_handle_from_ifkey(ifKey), &if_ip6_unused) == ESP_OK;
}

CHIP_ERROR ESP32Utils::GetWiFiStationProvision(Internal::DeviceNetworkInfo & netInfo, bool includeCredentials)
{
    wifi_config_t stationConfig;

    esp_err_t err = esp_wifi_get_config(WIFI_IF_STA, &stationConfig);
    if (err != ESP_OK)
    {
        return ESP32Utils::MapError(err);
    }

    VerifyOrReturnError(stationConfig.sta.ssid[0] != 0, CHIP_ERROR_INCORRECT_STATE);

    netInfo.NetworkId              = kWiFiStationNetworkId;
    netInfo.FieldPresent.NetworkId = true;
    memcpy(netInfo.WiFiSSID, stationConfig.sta.ssid,
           min(strlen(reinterpret_cast<char *>(stationConfig.sta.ssid)) + 1, sizeof(netInfo.WiFiSSID)));

    // Enforce that netInfo wifiSSID is null terminated
    netInfo.WiFiSSID[kMaxWiFiSSIDLength] = '\0';

    if (includeCredentials)
    {
        static_assert(sizeof(netInfo.WiFiKey) < 255, "Our min might not fit in netInfo.WiFiKeyLen");
        netInfo.WiFiKeyLen = static_cast<uint8_t>(min(strlen((char *) stationConfig.sta.password), sizeof(netInfo.WiFiKey)));
        memcpy(netInfo.WiFiKey, stationConfig.sta.password, netInfo.WiFiKeyLen);
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR ESP32Utils::SetWiFiStationProvision(const Internal::DeviceNetworkInfo & netInfo)
{
    wifi_config_t wifiConfig;

    char wifiSSID[kMaxWiFiSSIDLength + 1];
    size_t netInfoSSIDLen = strlen(netInfo.WiFiSSID);

    // Ensure that ESP station mode is enabled.  This is required before esp_wifi_set_config(ESP_IF_WIFI_STA,...)
    // can be called.
    ReturnErrorOnFailure(ESP32Utils::EnableStationMode());

    // Enforce that wifiSSID is null terminated before copying it
    memcpy(wifiSSID, netInfo.WiFiSSID, min(netInfoSSIDLen + 1, sizeof(wifiSSID)));
    if (netInfoSSIDLen + 1 < sizeof(wifiSSID))
    {
        wifiSSID[netInfoSSIDLen] = '\0';
    }
    else
    {
        wifiSSID[kMaxWiFiSSIDLength] = '\0';
    }

    // Initialize an ESP wifi_config_t structure based on the new provision information.
    memset(&wifiConfig, 0, sizeof(wifiConfig));
    memcpy(wifiConfig.sta.ssid, wifiSSID, min(strlen(wifiSSID) + 1, sizeof(wifiConfig.sta.ssid)));
    memcpy(wifiConfig.sta.password, netInfo.WiFiKey, min((size_t) netInfo.WiFiKeyLen, sizeof(wifiConfig.sta.password)));
    wifiConfig.sta.scan_method = WIFI_ALL_CHANNEL_SCAN;
    wifiConfig.sta.sort_method = WIFI_CONNECT_AP_BY_SIGNAL;

    // Configure the ESP WiFi interface.
    esp_err_t err = esp_wifi_set_config(WIFI_IF_STA, &wifiConfig);
    if (err != ESP_OK)
    {
        ChipLogError(DeviceLayer, "esp_wifi_set_config() failed: %s", esp_err_to_name(err));
        return ESP32Utils::MapError(err);
    }

    ChipLogProgress(DeviceLayer, "WiFi station provision set (SSID: %s)", netInfo.WiFiSSID);

    return CHIP_NO_ERROR;
}

CHIP_ERROR ESP32Utils::ClearWiFiStationProvision(void)
{
    wifi_config_t stationConfig;

    // Clear the ESP WiFi station configuration.
    memset(&stationConfig, 0, sizeof(stationConfig));
    esp_wifi_set_config(WIFI_IF_STA, &stationConfig);

    return CHIP_NO_ERROR;
}

CHIP_ERROR ESP32Utils::MapError(esp_err_t error)
{
    if (error == ESP_OK)
    {
        return CHIP_NO_ERROR;
    }
    if (error == ESP_ERR_NVS_NOT_FOUND)
    {
        return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
    }
    if (error == ESP_ERR_NVS_INVALID_LENGTH)
    {
        return CHIP_ERROR_BUFFER_TOO_SMALL;
    }
    return CHIP_ERROR(ChipError::Range::kPlatform, error);
}

/**
 * Given a CHIP error value that represents an ESP32 error, returns a
 * human-readable NULL-terminated C string describing the error.
 *
 * @param[in] buf                   Buffer into which the error string will be placed.
 * @param[in] bufSize               Size of the supplied buffer in bytes.
 * @param[in] err                   The error to be described.
 *
 * @return true                     If a description string was written into the supplied buffer.
 * @return false                    If the supplied error was not an ESP32 error.
 *
 */
bool ESP32Utils::FormatError(char * buf, uint16_t bufSize, CHIP_ERROR err)
{
    if (!err.IsRange(ChipError::Range::kPlatform))
    {
        return false;
    }

#if CHIP_CONFIG_SHORT_ERROR_STR
    const char * desc = NULL;
#else  // CHIP_CONFIG_SHORT_ERROR_STR
    const char * desc = esp_err_to_name((esp_err_t) err.GetValue());
#endif // CHIP_CONFIG_SHORT_ERROR_STR

    chip::FormatError(buf, bufSize, "ESP32", err, desc);

    return true;
}

/**
 * Register a text error formatter for ESP32 errors.
 */
void ESP32Utils::RegisterESP32ErrorFormatter()
{
    static ErrorFormatter sErrorFormatter = { ESP32Utils::FormatError, NULL };

    RegisterErrorFormatter(&sErrorFormatter);
}
