/************************************************************************
 * merge blocks into frame                                              *
 ************************************************************************/

#include <stdio.h>
#include "mergeframe.h"

void mergeframe_init(DOLProcess *p) {
    p->local->disp_nb = 0;
    p->local->send_size = 1;
    p->local->num_iter = 0;
}

int mergeframe_fire(DOLProcess *p) {
    int rx_size, ry_size;
    int mx_size, my_size; //picture size in units of MCUs
    int goodrows, goodcolumns;
    unsigned char *ColorBuffer = p->local->ColorBuffer;
    unsigned char *LineBuffer  = p->local->LineBuffer;
    int *dataBuff = p->local->dataBuff;

    dbgprintf(VERBOSE, "\tMERGEFRAME\tthread is alive !\n");

    //read picture size from demux
    DOL_read((void*)PORT_IN2, &p->local->y_s, sizeof(p->local->y_s), p);
    DOL_read((void*)PORT_IN2, &p->local->x_s, sizeof(p->local->x_s), p);

    //send size for each frame
    DOL_write((void*)PORT_OUT2, &p->local->x_s, sizeof(p->local->x_s), p);
    DOL_write((void*)PORT_OUT2, &p->local->y_s, sizeof(p->local->y_s), p);

    mx_size = intceil(p->local->x_s, MCU_sx);
    my_size = intceil(p->local->y_s, MCU_sy);
    //floor video frame size in pixel units, multiple of MCU
    rx_size = MCU_sx * intfloor(p->local->x_s, MCU_sx);
    ry_size = MCU_sy * intfloor(p->local->y_s, MCU_sy);
    goodrows = MCU_sy;
    goodcolumns = MCU_sx;

    //piece-wise processing
    for (int j = 0; j < my_size; j++) {
        for (int k = 0; k < mx_size; k++) {
            for (int l = 0; l < NB_SEND; l++){
                DOL_read((void*)PORT_IN1, &ColorBuffer[MAX_SEND * l],
                         MAX_SEND * sizeof(unsigned char), p);
            }

            //cut last row/column as needed
            //if ((p->local->y_s != ry_size) && (j == my_size - 1)) {
            //    goodrows = p->local->y_s - ry_size;
            //} else {
            //    goodrows = MCU_sy;
            //}

            //if ((p->local->x_s != rx_size) && (k == mx_size - 1)) {
            //    goodcolumns = p->local->x_s - rx_size;
            //} else {
            //    goodcolumns = MCU_sx;
            //}

            for (int l = 0; l < goodrows; l++) {
                memcpy(LineBuffer + k * MCU_sx + l * p->local->x_s,
                       ColorBuffer + l * MCU_sx, goodcolumns);
            }
        }

        for (int l = 0; l < (p->local->x_s * MCU_sy) / 4; l++) {
            dataBuff[l] =(*(LineBuffer + 4 * l))
                + (*(LineBuffer + 4 * l + 1) << 8)
                + (*(LineBuffer + 4 * l + 2) << 16)
                + (*(LineBuffer + 4 * l + 3) << 24);
        }
        DOL_write((void*)PORT_OUT1, dataBuff, p->local->x_s * MCU_sy, p);
    }

    p->local->disp_nb++;
    dbgprintf(VERBOSE | INFO, "\tMERGEFRAME\tdisplay %d\n", p->local->disp_nb);

    //end this process
    p->local->num_iter++;
    if (p->local->num_iter == NUMBER_OF_FRAMES) {
        DOL_detach(p);
        return 0;
    }
}
