#include "imagebuffer.h"
#include "mylogger.h"
#include <chrono>
using namespace std::chrono;

ImageBuffer::ImageBuffer(size_t buffer_size, QObject *parent) : QObject(parent), buffer_size(buffer_size) {
  buffer.resize(buffer_size, nullptr);
  qDebug() << "Imagebuffer constructor!";
}

void ImageBuffer::clear() {
  qDebug() << "Clear Image buffer!";

  for (auto & img: buffer) {
    if (img != nullptr)
      delete(img);
      img = nullptr;
  }
  resize(buffer_size);
}

size_t ImageBuffer::capacity() {
  return buffer.capacity();
}

double ImageBuffer::bufferPressure() {
  double pressure;
  size_t l = bufferLoad();
  mutex.lock();
  pressure = l / buffer_size * 100;
  mutex.unlock();
  return pressure;
}

size_t ImageBuffer::bufferLoad() {
  size_t l;
  mutex.lock();
  if (read_idx > head_idx){
    l = buffer_size - read_idx - head_idx;
  } else {
    l = head_idx - read_idx;
  }
  mutex.unlock();
  return l;
}

void ImageBuffer::resize(size_t new_size) {
  qDebug() << "Buffer Resize";
  mutex.lock();
  buffer_size = new_size;
  buffer.clear();
  buffer.resize(buffer_size, nullptr);
  framecounts.clear();
  framecounts.resize(buffer_size, 0);
  read_idx = 0;
  head_idx = 0;
  load = 0;
  framecount = 0;
  mutex.unlock();
}

void ImageBuffer::push(MyImage *img) {
  mutex.lock();
  head_idx += 1;
  framecount +=1;
  if (head_idx >= buffer_size) {
    head_idx = 0;
  }
  if (buffer[head_idx] != nullptr) {
    delete(buffer[head_idx]);
  }
  buffer[head_idx] = img;
  framecounts[head_idx] = framecount;
  load = load < buffer_size ? load +=1 : buffer_size;
  mutex.unlock();
}

bool ImageBuffer::bufferNotEmpty() {
  bool res;
  mutex.lock();
  res = load > 0;
  mutex.unlock();
  return res;
}

MyImage* ImageBuffer::read(size_t &framecount){
  MyImage *img = nullptr;
  mutex.lock();
  if (read_idx < head_idx) {
    read_idx += 1;
  } else if (read_idx > head_idx) {
    read_idx < buffer_size ? read_idx += 1 : read_idx = 0;
  } else {
    framecount = 0;
    return img;
  }
  img = buffer[read_idx];
  framecount = framecounts[read_idx];
  mutex.unlock();
  return img;
}

MyImage* ImageBuffer::readLast(size_t &framecount) {
  MyImage *img = nullptr;
  mutex.lock();
  img = buffer[head_idx];
  framecount = framecounts[head_idx];
  mutex.unlock();
  return img;
}

ImageBuffer::~ImageBuffer(){
  qDebug() << "Image buffer destructor";
  clear();
}