#include <Vector.h>
#include <Arduino.h>

#include "App.h"
#include "Bridge.h"
#include "error_codes.h"
#include "enums.h"
#include "constants.h"
#include "ModbusValue.h"

static Component *componentsArray[MAX_COMPONENTS];
static ModbusGateway *componentsArrayModbus[MAX_COMPONENTS];

App::App() : Component("APP", 0, Addon::ADDON_FLAGS_DEFAULT)
{
    DEBUG_INTERVAL = 1000;
    components.setStorage(componentsArray);
    nComponents.setStorage(componentsArrayModbus);
    debugTS = 0;
}

short App::setup()
{
    Log.verbose(F("* App:setup *" CR));
    uchar s = components.size();
    for (uchar i = 0; i < s; i++)
    {
        Component *component = components[i];
        if (!component->owner)
        {
            component->owner = this;
        }
        if (component->hasFlag(OBJECT_RUN_FLAGS::E_OF_SETUP))
        {
            component->setup();
        }
    }

    info();
    /*
    if (bridge)
    {
        bridge->onRegisterMethods(bridge);
    }*/
    return E_OK;
}

short App::registerComponents(Bridge *bridge)
{
    uchar s = components.size();
    for (uchar i = 0; i < s; i++)
    {
        Component *component = components[i];
        if (component->hasFlag(OBJECT_RUN_FLAGS::E_OF_DISABLED))
        {
            continue;
        }
        component->onRegisterMethods(bridge);
    }
    return E_OK;
}

short App::loop()
{
    timer.tick();
    now = millis();
    uchar s = components.size();
    for (uchar i = 0; i < s; i++)
    {
        Component *component = components[i];
        if (component->hasFlag(OBJECT_RUN_FLAGS::E_OF_LOOP))
        {
            component->now = now;
            component->loop();
        }
    }
    debug();
    return E_OK;
}
////////////////////////////////////////////////
//
//  Addon related functions

short App::numByFlag(ushort flag)
{
    uchar s = components.size();
    uchar l = 0;
    for (uchar i = 0; i < s; i++)
    {
        Component *component = components[i];
        if (!!(component->hasFlag(flag)))
        {
            l++;
        }
    }
    return l;
}

short App::debug()
{
    if (millis() - debugTS > DEBUG_INTERVAL)
    {
        uchar s = components.size();
        uchar nb = 0;
        for (uchar i = 0; i < s; i++)
        {
            Component *component = components[i];
            if (component->hasFlag(OBJECT_RUN_FLAGS::E_OF_DEBUG))
            {
                if (component->debug())
                {
                    Serial.println("\n");
                    nb++;
                }
            }
        }
        if (nb)
        {
            Serial.println("\n");
        }
        debugTS = millis();
    }
    return E_OK;
}

short App::info()
{
    uchar s = components.size();
    for (uchar i = 0; i < s; i++)
    {
        Component *component = components[i];
        if (component->hasFlag(OBJECT_RUN_FLAGS::E_OF_INFO))
        {
            component->info();
        }
    }
    return E_OK;
}

Component *App::byId(short id)
{
    uchar s = components.size();
    for (uchar i = 0; i < s; i++)
    {
        Component *component = components[i];
        if (component->id == id)
        {
            return component;
        }
    }
    return NULL;
}
