#include <subtitle.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

static void copy_line(subtitle_line_t* to, const subtitle_line_t* from)
{
    int i;
    for (i = 0; i < SUBTITLE_MAX_LINES; i++)
	to->line[i] = (from->line[i] && i < from->lines)
	    ? strdup(from->line[i]) : NULL;

    to->start = from->start;
    to->end = from->end;
    to->lines = from->lines;
}

static void free_line(subtitle_line_t* sl)
{
    int i;
    for (i = 0; i < sl->lines; i++)
    {
	free(sl->line[i]);
	sl->line[i] = NULL;
    }
    sl->start = 0;
    sl->end = 0;
    sl->lines = 0;
}

void subtitle_close(subtitles_t* st)
{
    int i;
    pthread_mutex_lock(&st->mutex);
    for (i = 0; i < st->count; i++)
    {
        int j;
	for (j = 0; j < SUBTITLE_MAX_LINES; j++)
	{
	    if (st->subtitle[i].line[j])
                free(st->subtitle[i].line[j]);
	}
    }
    free(st->subtitle);
    free(st->filename);
    pthread_mutex_destroy(&st->mutex);
    free(st);
}

void subtitle_set_fps(subtitles_t* st, double fps)
{
    st->fps = fps;
}

int subtitle_get(subtitle_line_t* sl, subtitles_t* st, double timepos)
{
    int lo = 0;
    int hi;
    unsigned int fp = (unsigned int) (timepos * 1000.0);
    subtitle_line_t* line = NULL;

    pthread_mutex_lock(&st->mutex);
    hi = st->count - 1;
    if (hi > 0)
    {
	if (st->frame_based && st->fps > 0.0)
	    fp = (unsigned int) (timepos * st->fps);

	//printf("get: %f -> %d  %f\n", timepos, fp, st->fps);
	while (lo < hi)
	{
	    int m = (lo + hi) / 2;

	    if (fp < st->subtitle[m].start)
		hi = m;
	    else if (fp >= st->subtitle[m + 1].start)
		lo = m + 1;
	    else
	    {
		lo = m;
		break;
	    }
	}
	if (st->subtitle[lo].start <= fp && fp < st->subtitle[lo].end)
	    line = &st->subtitle[lo];
    }
    //printf("pos %d    %p    %d   %d   %d\n", lo, line, fp, st->subtitle[lo].start, st->subtitle[lo].end);
    if (line)
    {
	if (!subtitle_line_equals(sl, line))
	{
	    free_line(sl);
	    copy_line(sl, line);
	}
    }
    else
	free_line(sl);

    pthread_mutex_unlock(&st->mutex);
    return (line != NULL);
}

int subtitle_get_lines(subtitles_t* st)
{
    return st->count;
}

subtitle_type subtitle_get_type(subtitles_t* st)
{
    return st->type;
}

subtitle_line_t* subtitle_line_new()
{
    subtitle_line_t* nl;
    nl = (subtitle_line_t*) malloc(sizeof(*nl));
    if (nl != NULL)
	memset(nl, 0, sizeof(*nl));
    return nl;
}

subtitle_line_t* subtitle_line_copy(const subtitle_line_t* sl)
{
    subtitle_line_t* nl;

    if (sl == NULL)
	return NULL;

    nl = subtitle_line_new();
    if (nl != NULL)
        copy_line(nl, sl);
    return nl;
}

int subtitle_line_equals(const subtitle_line_t* l1, const subtitle_line_t* l2)
{
    /*
     * for now we assume we have just one subtitle with the same time
     * and the line count
     */
    return (l1 != NULL && l2 != NULL
	    && l1->lines == l2->lines
	    && l1->start == l2->start
	    && l1->end == l2->end);
}

void subtitle_line_free(subtitle_line_t* sl)
{
    if (sl != NULL)
    {
        free_line(sl);
	free(sl);
    }
}
