#include "meshcore.h"
#include "lib/monocypher/monocypher-ed25519.h"
#include "meshcore/packets/advert.h"
#include "meshcore/packets/anonymous.h"
#include "meshcore/packets/control.h"
#include "meshcore/packets/encrypted.h"
#include "meshcore/packets/group.h"
#include "meshcore/stats.h"
#include "lib/base64.h"
#include "lib/cifra/aes.h"
#include "lib/cifra/sha2.h"
#include "lib/cifra/hmac.h"
#include "lib/config.h"
#include "meshframing.h"
#include "meshcore/packetstructs.h"

#define TAG "MeshCore"

// requires at least a 256 byte data


void processFrame (FrameStruct *frame) {
    printframeHeader (frame);
    if (frame->header & PAYLOAD_VERSION_3) {  // more than the version 0
        MESH_LOGW (TAG, "Frame too new, got version %d instead of 0", (frame->header & PAYLOAD_VERSION_3) >> 6);
    }

    unsigned char frameType = frame->header & PAYLOAD_TYPE_MASK;

    unsigned char index = 0;

    stats.packetsReceivedCount++;

    if ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_FLOOD ||
        (frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) {
        stats.receivedFloodCount++;
    }

    if ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_DIRECT ||
        (frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT) {
        stats.receivedDirectCount++;
    }


    if (frameType == PAYLOAD_TYPE_ANON_REQ) {
        decodeAnonReq (frame);

    } else if (frameType == PAYLOAD_TYPE_PATH || frameType == PAYLOAD_TYPE_REQ || frameType == PAYLOAD_TYPE_RESPONSE || frameType == PAYLOAD_TYPE_TXT_MSG) {
        iprintf ("  Typexd: 0x%02X\n", frameType);
        decodeEncryptedPayload (frame);

    } else if (frameType == PAYLOAD_TYPE_ACK) {
        uint32_t checkSum = frame->payload[index++];
        checkSum |= frame->payload[index++] << 8;
        checkSum |= frame->payload[index++] << 16;
        checkSum |= frame->payload[index++] << 24;
        // TODO add checking

    } else if (frameType == PAYLOAD_TYPE_ADVERT) {
        decodeAdvertisement (frame);
    } else if (frameType == PAYLOAD_TYPE_GRP_TXT || frameType == PAYLOAD_TYPE_GRP_DATA) {
        decodeGroupMessage (frame);
    } else if (frameType == PAYLOAD_TYPE_TRACE) {

    } else if (frameType == PAYLOAD_TYPE_MULTIPART) {

    } else if (frameType == PAYLOAD_TYPE_CONTROL) {
        if (frame->path.pathLen == 0) {
            decodeControlFrame (frame);
        }
        frame->header = 0xFF;

    } else if (frameType == PAYLOAD_TYPE_RAW_CUSTOM) {
        // not implemented
    } else {
        stats.packetsReceivedCount--;
    }
    MESH_LOGD (TAG, "Processed frame");
}
