#include "PngReader.h"
#include "PixClient.h"

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <endian.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#include "png.h"

#include "videodev.h"

#include <sys/time.h>
#include <sys/resource.h>

ClassImp(PngReader);

using namespace std;

char *PngReader::GetImg(unsigned int frame)
{
    char txt1[100];

    frame %= 333;

    sprintf(txt1, "file%04d.png", frame);

    // cout << "Reading PNG '" << txt1 << "'" << endl;

    char txt2[200];
    sprintf(txt2, "/home/caos/Dani/Cosy/smallleds/%s", txt1);
    //sprintf(txt2, "/home/caos/cosy.lp/pix/stable_1min/%s", txt1);

    //
    // open file
    //
    FILE *fd = fopen(txt2, "r");
    if (!fd)
    {
        cout << "Cannot open file." << endl;
        return 0;
    }
    //
    // allocate memory
    //
    png_structp fPng = png_create_read_struct(PNG_LIBPNG_VER_STRING,
                                              NULL, NULL, NULL);

    if (!fPng)
    {
        cout << "Warning: Unable to create PNG structure" << endl;
        fclose(fd);
        return 0;
    }


    png_infop fInfo = png_create_info_struct(fPng);

    if (!fInfo)
    {
        cout << "Warning: Unable to create PNG info structure" << endl;
        png_destroy_read_struct (&fPng, NULL, NULL);
        fclose(fd);
        return 0;
    }

    //
    // set jump-back point in case of errors
    //
    if (setjmp(fPng->jmpbuf))
    {
        cout << "longjmp Warning: PNG encounterd an error!" << endl;
        png_destroy_read_struct (&fPng, &fInfo, NULL);
        fclose(fd);
        return 0;
    }

    //
    // connect file to PNG-Structure
    //
    png_init_io(fPng, fd);

    // png_set_compression_level (fPng, Z_BEST_COMPRESSION);

    png_read_png(fPng, fInfo, 0, NULL);

    //
    // Write bitmap data
    //
    for (unsigned int y=0; y<576; y++)
        for (unsigned int x=0; x<768; x++)
            *(fImg+(y*768)+x) = fInfo->row_pointers[y][x];

    //
    // free memory
    //
    png_destroy_read_struct (&fPng, &fInfo, NULL);

    fclose(fd);

    return fImg; 
}

PngReader::PngReader(PixClient &client) : fClient(client)
{
    cout << "Starting thread..." << flush;
    pthread_create(&fThread, NULL, MapThread, this);
    cout << "done." << endl;

}

PngReader::~PngReader()
{
    cout << "Stopping thread..." << flush;
    pthread_cancel(fThread);
    cout << "done." << endl;
}

void *PngReader::MapThread(void *arg)
{
    PngReader *cam = (PngReader*)arg;

    // setpriority(PRIO_PROCESS, 0, 10);
    pthread_detach(pthread_self());

    cam->Thread();

    return 0;
}

void PngReader::Thread()
{
    fIsRunning = 1;
    usleep(3000000);
    int i=0;

    gettimeofday(&fTime, NULL);

    while (!fStop)
    {
        // if (i<536)
        // {
        GetImg(i);
        fClient.ProcessFrame(i++, (byte*)fImg, &fTime);
        // usleep(10000);
        // }
        // else exit();
        fTime.tv_sec += 1;
        usleep(1000);
    }


    fIsRunning = 0;
}

