/*
 * SubRip subtitle decoder
 * Copyright (c) 2010  Aurelien Jacobs <aurel@gnuage.org>
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "libavutil/avstring.h"
#include "libavutil/parseutils.h"
#include "avcodec.h"
#include "ass.h"
#include "ass_split.h"
#include "libavutil/mathematics.h"




static int html_color_parse(AVCodecContext *avctx, const char *str)
{
    uint8_t rgba[4];
    if (av_parse_color(rgba, str, strcspn(str, "\" >"), avctx) < 0)
        return -1;
    return rgba[0] | rgba[1] << 8 | rgba[2] << 16;
}

enum {
    PARAM_UNKNOWN = -1,
    PARAM_SIZE,
    PARAM_COLOR,
    PARAM_FACE,
    PARAM_NUMBER
};

typedef struct {
    char tag[128];
    char param[PARAM_NUMBER][128];
} SrtStack;


static int64_t get_pts(const char *buf)
{
   int i, v, hour, min, sec, hsec;
   
   for (i=0; i<2; i++) {
      if (sscanf(buf, "%d:%2d:%2d%*1[,.]%3d --> %*d:%*2d:%*2d%*1[,.]%3d",
         &hour, &min, &sec, &hsec, &v) == 5) {
         min += 60*hour;
      sec += 60*min;
      return sec*1000+hsec;
         }
         buf += strcspn(buf, "\n") + 1;
   }
   return AV_NOPTS_VALUE;
}

static const char *read_ts(const char *buf, int *ts_start, int *ts_end,
                           int *x1, int *y1, int *x2, int *y2)
{
    int i, hs, ms, ss, he, me, se;

    for (i=0; i<2; i++) {
        /* try to read timestamps in either the first or second line */
        int c = sscanf(buf, "%d:%2d:%2d%*1[,.]%3d --> %d:%2d:%2d%*1[,.]%3d"
                       "%*[ ]X1:%u X2:%u Y1:%u Y2:%u",
                       &hs, &ms, &ss, ts_start, &he, &me, &se, ts_end,
                       x1, x2, y1, y2);
        buf += strcspn(buf, "\n") + 1;
        if (c >= 8) {
            *ts_start = 100*(ss + 60*(ms + 60*hs)) + *ts_start/10;
            *ts_end   = 100*(se + 60*(me + 60*he)) + *ts_end  /10;
            return buf;
        }
    }
    return NULL;
}

static int srt_decode_frame(AVCodecContext *avctx,
                            void *data, int *got_sub_ptr, AVPacket *avpkt)
{
    AVSubtitle *sub = data;
    int ts_start, ts_end, x1 = -1, y1 = -1, x2 = -1, y2 = -1;
    char buffer[2048];
    const char *ptr = avpkt->data;
    const char *end = avpkt->data + avpkt->size;
    char *ptr2 = buffer;
    AVSubtitleRect **rects = NULL;

    if (avpkt->size <= 0)
        return avpkt->size;

    while (ptr < end && *ptr) {
        ptr = read_ts(ptr, &ts_start, &ts_end, &x1, &y1, &x2, &y2);
        if (!ptr)
            break;
        do {
           *ptr2++ = *ptr++;
        } while (ptr < end && *ptr && (ptr2 - buffer) < 2048);
        *ptr2 = 0;
        rects = av_realloc(sub->rects, (sub->num_rects+1) * sizeof(*sub->rects));
        if (!rects)
           return AVERROR(ENOMEM);
        
        sub->pts = av_rescale(ts_start, AV_TIME_BASE, 100);
        sub->start_display_time = 0;
        sub->rects = rects;
        sub->end_display_time = 10 * (ts_end - ts_start); 
        rects[sub->num_rects]       = av_mallocz(sizeof(*rects[0]));
        rects[sub->num_rects]->text = strdup(buffer);
        sub->num_rects++;
    }

    *got_sub_ptr = sub->num_rects > 0;
    return avpkt->size;
}

AVCodec ff_srt_decoder = {
    .name         = "srt",
    .long_name    = NULL_IF_CONFIG_SMALL("SubRip subtitle"),
    .type         = AVMEDIA_TYPE_SUBTITLE,
    .id           = CODEC_ID_SRT,
    .init         = ff_ass_subtitle_header_default,
    .decode       = srt_decode_frame,
};
