/*
 * Copyright (C) 2020-2021 Aloysius Indrayanto
 *
 * This file is part of the eCxx library, see LICENSE file for the license details.
 */

/*
 * ----------------------------------------------------------------------------------
 * The code in this file is copied (with a slight modifications) from:
 *     LwipIntf.cpp
 * ----------------------------------------------------------------------------------
 * This file is part of the esp8266 core for Arduino environment.
 *
 * This library is free software; you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation; either version 2.1 of the License, or (at your option) any later
 * version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along
 * with this library; if not, write to the Free Software Foundation, Inc., 51
 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 * ----------------------------------------------------------------------------------
 */


#include <lwip/dhcp.h>

#include "LwipIntf.h"


namespace eCxx {

namespace NodeMCU {


bool LwipIntf::ipAddressReorder(const IPAddress& local_ip, const IPAddress& arg1, const IPAddress& arg2, const IPAddress& arg3, IPAddress& gateway, IPAddress& netmask, IPAddress& dns1)
{
    // To allow compatibility, check first octet of 3rd argument;
    // if 255, interpret as ESP order, otherwise Arduino order
    gateway = arg1;
    netmask = arg2;
    dns1    = arg3;

    if(netmask[0] != 255) {
        // Octet is not 255 - interpret as Arduino order
        gateway = arg2;
        netmask = (arg3[0] == 0) ? IPAddress(255, 255, 255, 0)
                                 : arg3; // If argument order is Arduino and the 4th argument is not given, assign default
        dns1    = arg1;
    }

    // Check whether all is IPv4 (or gateway not set)
    if( !( local_ip.isV4() && netmask.isV4() && ( !gateway.isSet() || gateway.isV4() ) ) ) return false;

    // IP and gateway must be in the same netmask
    if( gateway.isSet() && ( local_ip.v4() & netmask.v4() ) != ( gateway.v4() & netmask.v4() ) ) return false;

    return true;
}


WString LwipIntf::hostname()
{ return wifi_station_get_hostname(); }


bool LwipIntf::hostname(const char* aHostname)
{
    size_t len = strlen(aHostname);

    // SDK limit is 32
    if(len == 0 || len > 32) {
        DEBUGV("WiFi.(set)hostname(): empty or large(>32) name\n");
        return false;
    }

    // Check RFC compliance
    bool compliant = (len <= 24);

    for(size_t i = 0; compliant && i < len; ++i) {
        if( !isalnum(aHostname[i]) && aHostname[i] != '-' ) {
            compliant = false;
            break;
        }
    }

    if(aHostname[len - 1] == '-') compliant = false;

    if(!compliant) {
        DEBUGV("hostname '%s' is not compliant with RFC952\n", aHostname);
    }

    bool ret = wifi_station_set_hostname(aHostname);
    if(!ret) {
        DEBUGV("WiFi.hostname(%s): wifi_station_set_hostname() failed\n", aHostname);
        return false;
    }

    // Inform dhcp server for this change, using lwip_renew() looping through all existing interface;
    // harmless for AP
    for(netif* intf = netif_list; intf; intf = intf->next) {
        // Unconditionally update all known interfaces
        intf->hostname = wifi_station_get_hostname();

        if(netif_dhcp_data(intf) != nullptr) {
            // Renew already started DHCP leases
            err_t lwipret = dhcp_renew(intf);
            if(lwipret != ERR_OK) {
                DEBUGV("WiFi.hostname(%s): lwIP error %d on interface %c%c (index %d)\n", intf->hostname, (int)lwipret, intf->name[0], intf->name[1], intf->num);
                ret = false;
            }
        }
    }

    return ret && compliant;
}


} // namespace NodeMCU

} // namespace eCxx
