/*
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
 *
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
 */

#include "stats/aomstats.h"

#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>

#include "aom_dsp/aom_dsp_common.h"
#include "common/tools_common.h"

int stats_open_file(stats_io_t *stats, const char *fpf, int pass) {
  int res;
  stats->pass = pass;

  if (pass == 0) {
    stats->file = fopen(fpf, "wb");
    stats->buf.sz = 0;
    stats->buf.buf = NULL;
    res = (stats->file != NULL);
  } else {
    size_t nbytes;

    stats->file = fopen(fpf, "rb");

    if (stats->file == NULL) fatal("First-pass stats file does not exist!");

    if (fseek(stats->file, 0, SEEK_END))
      fatal("First-pass stats file must be seekable!");

    stats->buf.sz = stats->buf_alloc_sz = ftell(stats->file);
    rewind(stats->file);

    stats->buf.buf = malloc(stats->buf_alloc_sz);

    if (!stats->buf.buf)
      fatal("Failed to allocate first-pass stats buffer (%lu bytes)",
            (unsigned int)stats->buf_alloc_sz);

    nbytes = fread(stats->buf.buf, 1, stats->buf.sz, stats->file);
    res = (nbytes == stats->buf.sz);
  }

  return res;
}

int stats_open_mem(stats_io_t *stats, int pass) {
  int res;
  stats->pass = pass;

  if (!pass) {
    stats->buf.sz = 0;
    stats->buf_alloc_sz = 64 * 1024;
    stats->buf.buf = malloc(stats->buf_alloc_sz);
  }

  stats->buf_ptr = stats->buf.buf;
  res = (stats->buf.buf != NULL);
  return res;
}

void stats_close(stats_io_t *stats, int last_pass) {
  if (stats->file) {
    if (stats->pass == last_pass) {
      free(stats->buf.buf);
    }

    fclose(stats->file);
    stats->file = NULL;
  } else {
    if (stats->pass == last_pass) free(stats->buf.buf);
  }
}

void stats_write(stats_io_t *stats, const void *pkt, size_t len) {
  if (stats->file) {
    (void)fwrite(pkt, 1, len, stats->file);
    return;
  }
  assert(stats->buf.sz <= stats->buf_alloc_sz);
  assert(0 < stats->buf_alloc_sz);
  if (stats->buf.sz + len > stats->buf_alloc_sz) {
    // Grow by a factor of 1.5 each time, for amortized constant time.
    // Also make sure there is enough room for the data.
    size_t new_sz = AOMMAX((3 * stats->buf_alloc_sz) / 2, stats->buf.sz + len);
    char *new_ptr = realloc(stats->buf.buf, new_sz);

    if (new_ptr) {
      stats->buf_ptr = new_ptr + (stats->buf_ptr - (char *)stats->buf.buf);
      stats->buf.buf = new_ptr;
      stats->buf_alloc_sz = new_sz;
    } else {
      fatal("Failed to realloc firstpass stats buffer.");
    }
  }

  memcpy(stats->buf_ptr, pkt, len);
  stats->buf.sz += len;
  stats->buf_ptr += len;
}

aom_fixed_buf_t stats_get(stats_io_t *stats) { return stats->buf; }
