/* Copyright 2016 Google Inc. All Rights Reserved.
   Author: zip753@gmail.com (Ivan Nikulin)

   Distributed under MIT license.
   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/

/* Backward reference visualization tool. Accepts file with backward references
   as an input and produces PGM image with histogram of those references. */

#include <algorithm> /* min */
#include <cassert>
#include <cstring> /* memset */
#include <cmath> /* log, round */
#include <cstdio> /* fscanf, fprintf */
#include <cstdint>

#include <gflags/gflags.h>
using gflags::ParseCommandLineFlags;

#include "third_party/absl/flags/flag.h"
#include "read_dist.h"

DEFINE_int32(height, 1000, "Height of the resulting histogam.");
DEFINE_int32(width, 8000, "Width of the resulting histogam.");
DEFINE_int32(size, 1e8, "Size of the compressed file.");
DEFINE_int32(brotli_window, -1, "Size of brotli window in bits.");
DEFINE_uint64(min_distance, 0, "Minimum distance.");
DEFINE_uint64(max_distance, 1 << 30, "Maximum distance.");
DEFINE_bool(with_copies, false, "True if input contains copy length.");
DEFINE_bool(simple, false, "True if using only black and white pixels.");
DEFINE_bool(linear, false, "True if using linear distance mapping.");
DEFINE_uint64(skip, 0, "Number of bytes to skip.");

inline double DistanceTransform(double x) {
  static bool linear = absl::GetFlag(FLAGS_linear);
  if (linear) {
    return x;
  } else {
    /* Using log^2 scale because log scale produces big white gap at the bottom
       of image. */
    return log(x) * log(x);
  }
}

/* Mapping pixel density on arc function to increase contrast. */
inline double DensityTransform(double x) {
  double z = 255 - x;
  return sqrt(255 * 255 - z * z);
}

inline int GetMaxDistance() { return absl::GetFlag(FLAGS_max_distance); }

void AdjustPosition(int* pos) {
  static uint32_t offset = 0;
  static int last = 0;
  static uint32_t window_size = (1 << absl::GetFlag(FLAGS_brotli_window));
  assert(*pos >= 0 && *pos < window_size);
  if (*pos < last) {
    offset += window_size;
  }
  last = *pos;
  *pos += offset;
}

void BuildHistogram(FILE* fin, int** histo) {
  int height = absl::GetFlag(FLAGS_height);
  int width = absl::GetFlag(FLAGS_width);
  int skip = absl::GetFlag(FLAGS_skip);
  size_t min_distance = absl::GetFlag(FLAGS_min_distance);

  printf("height = %d, width = %d\n", height, width);

  for (int i = 0; i < height; i++) {
    for (int j = 0; j < width; j++) {
      histo[i][j] = 0;
    }
  }

  int max_pos = absl::GetFlag(FLAGS_size) - skip;
  double min_dist = min_distance > 0 ? DistanceTransform(min_distance) : 0;
  double max_dist = DistanceTransform(GetMaxDistance()) - min_dist;
  int copy, pos, distance, x, y;
  double dist;
  while (ReadBackwardReference(fin, &copy, &pos, &distance)) {
    if (pos == -1) continue;  // In case when only insert is present.
    if (distance < min_distance || distance >= GetMaxDistance()) continue;
    if (absl::GetFlag(FLAGS_brotli_window) != -1) {
      AdjustPosition(&pos);
    }
    if (pos >= skip && distance <= pos) {
      pos -= skip;
      if (pos >= max_pos) break;
      dist = DistanceTransform(static_cast<double>(distance)) - min_dist;

      x = std::min(static_cast<int>(round(dist / max_dist * height)),
                   height - 1);
      y = 1ul * pos * width / max_pos;
      if (!(y >= 0 && y < width)) {
        printf("pos = %d, max_pos = %d, y = %d\n", pos, max_pos, y);
        assert(y >= 0 && y < width);
      }

      if (absl::GetFlag(FLAGS_with_copies)) {
        int right = 1ul * (pos + copy - 1) * width / max_pos;
        if (right < 0) {
          printf("pos = %d, distance = %d, copy = %d, y = %d, right = %d\n",
                  pos, distance, copy, y, right);
          assert(right >= 0);
        }
        if (y == right) {
          histo[x][y] += copy;
        } else {
          int pos2 = static_cast<int>(ceil(1.0 * (y + 1) * max_pos / width));
          histo[x][y] += pos2 - pos;
          for (int i = y + 1; i < right && i < width; ++i) {
            histo[x][i] += max_pos / width;  // Sometimes 1 more, but who cares.
          }
          // Make sure the match doesn't go beyond the image.
          if (right < width) {
            pos2 = static_cast<int>(ceil(1.0 * right * max_pos / width));
            histo[x][right] += pos + copy - 1 - pos2 + 1;
          }
        }
      } else {
        histo[x][y]++;
      }
    }
  }
}

void ConvertToPixels(int** histo, uint8_t** pixel) {
  int height = absl::GetFlag(FLAGS_height);
  int width = absl::GetFlag(FLAGS_width);

  int maxs = 0;
  for (int i = 0; i < height; i++) {
    for (int j = 0; j < width; j++) {
      if (maxs < histo[i][j]) maxs = histo[i][j];
    }
  }

  bool simple = absl::GetFlag(FLAGS_simple);
  double max_histo = static_cast<double>(maxs);
  for (int i = 0; i < height; i++) {
    for (int j = 0; j < width; j++) {
      if (simple) {
        pixel[i][j] = histo[i][j] > 0 ? 0 : 255;
      } else {
        pixel[i][j] = static_cast<uint8_t>(
            255 - DensityTransform(histo[i][j] / max_histo * 255));
      }
    }
  }
}

void DrawPixels(uint8_t** pixel, FILE* fout) {
  int height = absl::GetFlag(FLAGS_height);
  int width = absl::GetFlag(FLAGS_width);

  fprintf(fout, "P5\n%d %d\n255\n", width, height);
  for (int i = height - 1; i >= 0; i--) {
    fwrite(pixel[i], 1, width, fout);
  }
}

int main(int argc, char* argv[]) {
  base::ParseCommandLine(&argc, &argv);
  if (argc != 3) {
    printf("usage: draw_histogram.cc data output_file\n");
    return 1;
  }

  int height = absl::GetFlag(FLAGS_height);
  int width = absl::GetFlag(FLAGS_width);

  FILE* fin = fopen(argv[1], "r");
  FILE* fout = fopen(argv[2], "wb");

  if (fin != nullptr && fout != nullptr) {
    uint8_t** pixel = new uint8_t*[height];
    int** histo = new int*[height];
    for (int i = 0; i < height; i++) {
      pixel[i] = new uint8_t[width];
      histo[i] = new int[width];
    }

    BuildHistogram(fin, histo);

    ConvertToPixels(histo, pixel);

    DrawPixels(pixel, fout);
  }

  if (fin) fclose(fin);
  if (fout) fclose(fout);

  return 0;
}
