/*==============================================================================

FICHIER     : [dvdcell.c]

DATE        : 2006/02/0015 21:54:36

CREATEUR    : [Linux!jef]

COMMENTAIRE :
		Released under GPL license, see gnu.org
================================================================================

==============================================================================*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <memory.h>

#include "const.h"
#include "globals.h"
#include "dvdinfo.h"
#include "dvdcell.h"
#include "systools.h"
#include "dvdtools.h"

/*@$#[dvdcell.c] static proto. AutoProtoSigV1.1. date: 107/12/17 23:14:24 */
#include "proto.h"
#ifdef __cplusplus
extern "C" {
#endif
static int IsSelected PROTO((Cell_t *c, int noPisteVideo));
static int CellExist PROTO((CellArray_t *ca, int vts, uint32_t *start, uint32_t *end));
static void UnSelectLastCell PROTO((CellArray_t *ca));
#ifdef __cplusplus
}
#endif
/*@$% end of AutoProtoSigV1.1 (Dont remove this line) [-I ../include]*/

char DbgLevels[256];


/*------------------------------------------------------------------------------
	NEWCELL-
Linux!jef 2005/12/28 21:15:15
------------------------------------------------------------------------------*/

Cell_t * NewCell( CellArray_t * ca )
{
	Cell_t * c;
	int idx = ca->nbCells;
	int size = (idx + 1) * sizeof( Cell_t );

	ca->cells =(Cell_t *)realloc( ca->cells, size );
	c = ca->cells + idx;
	memset( c, 0, sizeof(*c));
	c->idx = idx;
	ca->nbCells++;
	return( c );
}
/*------------------------------------------------------------------------------
	NEWTITLESET-
Linux!jef 2006/01/16 21:21:20
------------------------------------------------------------------------------*/

TitleSet_t * NewTitleSet( TitleArray_t * ta )
{
	TitleSet_t * t;
	int idx = ta->nbTitles;
	int size = (idx + 1) * sizeof( TitleSet_t );

	ta->titles =(TitleSet_t *)realloc( ta->titles, size );
	t = ta->titles + idx;
	memset( t, 0, sizeof(*t));
	ta->nbTitles++;
	return( t );
}

/*------------------------------------------------------------------------------
	NEWVOBU-
Linux!jef 2006/01/18 22:15:52
------------------------------------------------------------------------------*/

Vobu_t * NewVobu( VobuArray_t * va, uint32_t oldSector )
{
	Vobu_t * v;
	int idx = va->nbVobu;
	int size = (idx + 1) * sizeof( Vobu_t );
	int i;

	va->vobus =(Vobu_t *)realloc( va->vobus, size );
	v = va->vobus + idx;
	memset( v, 0, sizeof(*v));
	for( i = 0; i < 8; i++ ) v->firstAudio[i] = -1;
	for( i = 0; i < 32; i++ ) v->firstSubp[i] = -1;
	v->firstVideo = -1;
	v->idx = idx;
	v->oldSector = oldSector;
//!!	DBG('b',fprintf(stderr,"%s: idx: %d\n", __FUNCTION__, idx ););

	va->nbVobu++;
	return( v );
}


/*------------------------------------------------------------------------------
	ISSELECTED-
Linux!jef 2005/12/29 21:10:05
------------------------------------------------------------------------------*/
static int IsSelected( Cell_t * c, int noPisteVideo )
{
	int vts = Ifo_zero->tt_srpt->title[noPisteVideo].title_set_nr;
	int title_set_nr;
	int vts_ttn;
	pgcit_t *vts_pgcit;
	pgc_t *pgc;
	int i;
	int cell = 0;

	if( vts != c->vts )	return( 0 );
	vts_pgcit = Ifo[vts]->vts_pgcit;
	vts_ttn = Ifo_zero->tt_srpt->title[noPisteVideo].vts_ttn;
	title_set_nr = Ifo_zero->tt_srpt->title[noPisteVideo].title_set_nr;
	pgc = vts_pgcit->pgci_srp[Ifo[title_set_nr]->vts_ptt_srpt->title[vts_ttn - 1].ptt[0].pgcn - 1].pgc;

	for( i = 0; i < pgc->nr_of_programs; i++ ) {
		int next;

		if( i == pgc->nr_of_programs - 1)
			next = pgc->nr_of_cells + 1;
		else
			next = pgc->program_map[i + 1];

		while (cell < next - 1) {
			unsigned int s = pgc->cell_playback[cell].first_sector;
			unsigned int e = pgc->cell_playback[cell].last_sector;

			if( c->startSector >= s && c->startSector <= e )	return( 1 );
			cell++;
		}
	}
	return( 0 );
}
/*------------------------------------------------------------------------------
	UNSELECTLASTCELL-
Linux!jef 2007/01/19 22:52:11
------------------------------------------------------------------------------*/

static void UnSelectLastCell( CellArray_t * ca )
{
	int i;

	for( i = ca->nbCells -1; i >= 0; i-- ) {
		Cell_t * c = ca->cells + i;

		if( c->selected ) {
			c->selected = 0;
			break;
		}
	}
}
/*------------------------------------------------------------------------------
	CELLEXIST-
Linux!jef 2006/01/25 01:11:11
------------------------------------------------------------------------------*/

static int CellExist( CellArray_t * ca, int vts, uint32_t * start, uint32_t * end )
{
	int i;

	for( i = 0; i < ca->nbCells; i++ ) {
		Cell_t * c = ca->cells + i;

		if( c->vts == vts ) {
			if( c->startSector <= *start && c->lastSector >= *end ) return( 1 );
#if 0
			if( c->startSector <= *start ) {
				*start = c->lastSector + 1;
			}
			else {
				*end = c->startSector - 1;
			}
#endif
		}
	}
	if( *start >= *end )	return( 1 );
	return( 0 );
}


/*------------------------------------------------------------------------------
	BUILDCELLS-
Linux!jef 2005/12/28 21:18:16
------------------------------------------------------------------------------*/

int BuildCells( int noPisteVideo, CellArray_t * ca, int lastF )
{
	int nrTS = Ifo_zero->vmgi_mat->vmg_nr_of_title_sets;
	int i,j,k;

	DBG('b',fprintf(stderr,"%s: nrTS=%d noPisteVideo=%d\n", __FUNCTION__, nrTS, noPisteVideo ););
	for( k = 1; k <= nrTS; k++ ) {
		ifo_handle_t * ifo = Ifo[k];
		int vts_ttn, title_set_nr;

		if( !ifo->vtsi_mat )	continue;
		DBG('b',fprintf(stderr,"VTS: %d PGCS: %d ifo: %p\n", k, ifo->vts_pgcit->nr_of_pgci_srp, ifo ););

		vts_ttn = Ifo_zero->tt_srpt->title[noPisteVideo].vts_ttn;
		title_set_nr = Ifo_zero->tt_srpt->title[noPisteVideo].title_set_nr;

		i = Ifo[title_set_nr]->vts_ptt_srpt->title[vts_ttn - 1].ptt[0].pgcn - 1;
//		for( i = 0; i < ifo->vts_pgcit->nr_of_pgci_srp; i++ )
		{
			pgc_t * pgc = ifo->vts_pgcit->pgci_srp[i].pgc;
			cell_playback_t * cell_playback = pgc->cell_playback;
			int nr = pgc->nr_of_cells;
			DBG('b',fprintf(stderr,"NrOfCells: %d\n", nr ););
			for( j = 0; j < nr; j++ ) {
				uint32_t start = cell_playback[j].first_sector;
				uint32_t end = cell_playback[j].last_sector;

				if( !CellExist( ca, k, &start, &end ) ) {
					Cell_t * c = NewCell( ca );

					c->vts = k;
					c->ifo = ifo;
					c->pgc = pgc;
					c->startSector = start;
					c->lastSector = end;
					c->selected = IsSelected( c, noPisteVideo );
					c->chapter = j;
				}
			}
		}
	}
	if( lastF )	UnSelectLastCell( ca );

	DBG('b',fprintf(stderr,"NrCells: %d\n", ca->nbCells );
	long long tSize = 0;
	for( i = 0; i < ca->nbCells; i++ ) {
		Cell_t * c = ca->cells + i;
		long long size;

		fprintf(stderr,"Cell%d: ", i);
		size = (long long)(c->lastSector - c->startSector + 1) * SECTOR_SIZE;
		tSize += size;
		fprintf(stderr,"vts: %d ", c->vts );
		fprintf(stderr,"start: %u end: %u ", c->startSector, c->lastSector );
		fprintf(stderr,"size: %s ", LLSize2Giga( size ) );
		fprintf(stderr,"selected: %d\n", c->selected );
	}
	fprintf(stderr,"Total size: %s\n", LLSize2Giga( tSize ) );
	);
	return( 0 );
}

/*------------------------------------------------------------------------------
	FREECELLARRAY-
Linux!jef 2005/12/28 21:30:33
------------------------------------------------------------------------------*/

void FreeCellArray( CellArray_t * ca )
{
	int i;

	for( i = 0; i < ca->nbCells; i++ ) {
		Cell_t * c = ca->cells + i;
		VobuArray_t * va = &c->va;

		if( va->nbVobu ) {
			free( va->vobus );
			va->nbVobu = 0;
		}
	}
	if( ca->nbCells ) {
		free( ca->cells );
	}
	ca->cells = NULL;
	ca->nbCells = 0;
}

/*------------------------------------------------------------------------------
	COUNTSELECTEDCELLS-
Linux!jef 2006/01/26 21:29:53
------------------------------------------------------------------------------*/

int CountSelectedCells( CellArray_t * ca )
{
	int i;
	int count = 0;

	for( i = 0; i < ca->nbCells; i++ ) {
		Cell_t * c = ca->cells + i;

		if( c->selected )	count++;
	}
	return( count );
}

/*------------------------------------------------------------------------------
	DUMPVOBUS-
Linux!jef 2006/01/18 23:06:39
------------------------------------------------------------------------------*/

void DumpVobus( Cell_t * c )
{
	int i;

	DBG('b',fprintf(stderr,"Vobus: number: %d\n", c->va.nbVobu ););
	for( i = 0; i < c->va.nbVobu; i++ ) {
		Vobu_t * v = c->va.vobus + i;

		DBG('b',fprintf(stderr,"Vobus%d: (%u)=>(%u,%u)\n", v->idx, v->oldSector, v->newSector, v->newSector + v->size ););
	}
}
