#include "main.h"
#include "bsprender2.h"
#include "avikit.h"

#define MAX_MAP_VIDS 16

#define NUM_AUDIO_BUFFS 4

typedef struct
{
bool used;
bool usable;
AVIKit*Avi;
texture_t*tex;
int xsize,ysize;
char*frame_buffer;

float frame;
int last_uploaded_frame;

int sample_rate;
int num_channels;
bool is16bit;

byte*audio_buff[NUM_AUDIO_BUFFS];
long timeoffsets[NUM_AUDIO_BUFFS];
int current_audio_buffer;

}avi_texture_t;

avi_texture_t Avis[MAX_MAP_VIDS];

avi_texture_t*AllocAviTexture()
{
for(int i=0;i {
if (!Avis[i].used)
{
Avis[i].used=true;
return &Avis[i];
}
}
FAIL("AllocAviTexture(): no free slots!");
}

bool CheckAviError(AVIKit*avi)
{
int err;
char *emsg;

bool ret=false;

while ((err = avi->getError(&emsg)) != AVIKIT_NOERROR)
{
ret=true;
switch (err)
{
case AVIKIT_ERROR_BADFILE: // "No handler found, or file does not exist."
case AVIKIT_ERROR_BADFORMAT: // "Corrupt AVI or unknown format."
case AVIKIT_ERROR_MEMERROR: // "Not enough memory to open AVI."
case AVIKIT_ERROR_DISKERROR: // "Disk error attempting to read AVI."

// errors opening video
case AVIKIT_ERROR_NOVIDEO: // "No video stream found in specified file."
case AVIKIT_ERROR_VIDEOERROR: // "VFW failed to read video stream."
RPRINTF("LoadAviForTexture() error:%s",emsg);
break;

// errors opening audio
case AVIKIT_ERROR_ACM: // "ACM failed to open conversion stream."
RPRINTF("LoadAviForTexture(): ACM failed to open conversion stream (is the codec installed?)");
break;

case AVIKIT_ERROR_ACMCODEC: // "ACM does not support this audio codec." (WMA).
default:
RPRINTF("LoadAviForTexture() error:%s",emsg);
break;
}
}
return ret;
}

void LoadAviForTexture(texture_t*tex)
{
avi_texture_t*avi_tex=AllocAviTexture();
avi_tex->tex=tex;

char vidname[8];
sscanf(tex->name,"avi@%s",vidname);



//glGenTextures(1,(GLuint*)&tex->gl_texturenum);
tex->gl_texturenum=1;

avi_tex->Avi=new AVIKit(VA("data/textures/video/%s.avi",vidname));

if (CheckAviError(avi_tex->Avi))
{
delete avi_tex->Avi;
avi_tex->used=false;
return;
}

long xsize,ysize;
float len;

avi_tex->Avi->getVideoInfo(&xsize,&ysize,&len);
avi_tex->frame_buffer=(char*)Z_Malloc(xsize*ysize*3);
avi_tex->xsize=xsize;
avi_tex->ysize=ysize;

glBindTexture(GL_TEXTURE_2D,tex->gl_texturenum);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, xsize,ysize, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);

long sample_rate,bps,channels;
bool is16bit;

avi_tex->Avi->getAudioInfo(&sample_rate,&bps,&channels,&is16bit);
avi_tex->sample_rate=sample_rate;

avi_tex->is16bit=is16bit;
avi_tex->num_channels=channels;

for(int i=0;i {
avi_tex->audio_buff[i]=(byte*)Z_Malloc(sample_rate*channels* bps*is16bit ? 2:1);
avi_tex->timeoffsets[i]=0;
}
avi_tex->current_audio_buffer=0;


RPRINTF("Loading avi %s - %d frames,",VA("textures/video/%s.avi",vidname),avi_tex->Avi->NumVideoFrames());
RPRINTF("Audio: %d Hz %d bps %d channels %s",sample_rate,bps,channels,is16bit ? "16bit" : "8bit");


}

void DBG_DumpFrame(avi_texture_t*tex)
{
FILE*fp=fopen(VA("%s.raw",tex->tex->name),"wb");
fwrite(tex->frame_buffer,tex->xsize*tex->ysize*3,1,fp);
fclose(fp);
}

void RefreshBspAvis()
{
// return;
for(int i=0;i {
avi_texture_t*tex=&Avis[i];

if (!tex->used) continue;

tex->frame+=R_FrameTime()*25;



if (tex->frame>tex->Avi->NumVideoFrames())
tex->frame=0;

int f=tex->Avi->getVideoFrameNumber(tex->frame/25);
tex->Avi->getVideoFrame(tex->frame_buffer, tex->frame);

//RefreshAviAudio(tex);

if (f!=tex->last_uploaded_frame)
{
glBindTexture(GL_TEXTURE_2D,tex->tex->gl_texturenum);
glTexSubImage2D(GL_TEXTURE_2D, 0,0, 0, tex->xsize,tex->ysize,GL_RGB, GL_UNSIGNED_BYTE, tex->frame_buffer);
//glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,tex->xsize,tex->ysize,0,GL_RGB,GL_UNSIGNED_BYTE,tex->frame_buffer);

tex->last_uploaded_frame=f;
}

}
}