/*
 * 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 few modifications) from:
 *     LwipIntfCB.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 "LwipIntf.h"
#include "Schedule.h"


#define NETIF_STATUS_CB_SIZE 3


static int32_t netifStatusChangeListLength = 0;

static LwipIntf::CBType netifStatusChangeList[NETIF_STATUS_CB_SIZE];

// Override the default empty weak function
extern "C" void netif_status_changed(struct netif* netif)
{
    for(int32_t i = 0; i < netifStatusChangeListLength; ++i) {
        if( netifStatusChangeList[i] ) netifStatusChangeList[i](netif);
    }
}


namespace eCxx {

namespace NodeMCU {


bool LwipIntf::stateUpCB(CBType&& cb)
{
    if( netifStatusChangeListLength >= NETIF_STATUS_CB_SIZE ) {
        DEBUGV("NETIF_STATUS_CB_SIZE is too small\n");
        return false;
    }

#ifdef __ECXX_NODEMCU_SCHEDULE_USE_ECXX_FUNCTION

    netifStatusChangeList[netifStatusChangeListLength++] = [cb](netif* nif) {
        if( netif_is_up(nif) ) {
            std::function<void()> fn = [cb, nif]() {
                cb(nif);
            };
            NodeMCU::scheduleFunction(fn);
        }
    };

#else

    netifStatusChangeList[netifStatusChangeListLength++] = [cb](netif* nif) {
        if( netif_is_up(nif) ) {
            NodeMCU::scheduleFunction( [cb, nif]() {
                cb(nif);
            } );
        }
    };

#endif

    return true;
}


void LwipIntf::clearAllStateUpCB()
{
    netifStatusChangeListLength = 0;

    for(int32_t i = 0; i < NETIF_STATUS_CB_SIZE; ++i) {
        netifStatusChangeList[i] = nullptr;
    }
}


} // namespace NodeMCU

} // namespace eCxx
