#include <condition_variable>
#include <fstream>
#include <mutex>
#include <random>
#include <thread>

#include "aos/vision/blob/codec.h"
#include "aos/vision/blob/find_blob.h"
#include "aos/vision/events/socket_types.h"
#include "aos/vision/events/udp.h"
#include "y2019/jevois/camera/image_stream.h"
#include "y2019/jevois/camera/reader.h"
#include "y2019/jevois/serial.h"
#include "y2019/jevois/structures.h"
#include "y2019/jevois/uart.h"
#include "y2019/vision/image_writer.h"
#include "y2019/vision/target_finder.h"

// This has to be last to preserve compatibility with other headers using AOS
// logging.
#include "glog/logging.h"

using ::aos::monotonic_clock;
using ::aos::events::DataSocket;
using ::aos::events::RXUdpSocket;
using ::aos::events::TCPServer;
using ::aos::vision::DataRef;
using ::aos::vision::Int32Codec;
using aos::vision::Segment;
using ::y2019::jevois::open_via_terminos;

class CameraStream : public ::y2019::camera::ImageStreamEvent {
 public:
  CameraStream(::aos::vision::CameraParams params, const ::std::string &fname)
      : ImageStreamEvent(fname, params) {}

  void ProcessImage(DataRef data, monotonic_clock::time_point monotonic_now) {
    LOG(INFO) << "got frame: " << data.size();

    if (on_frame_) on_frame_(data, monotonic_now);
  }

  void set_on_frame(
      const std::function<void(DataRef, monotonic_clock::time_point)>
          &on_frame) {
    on_frame_ = on_frame;
  }

 private:
  std::function<void(DataRef, monotonic_clock::time_point)> on_frame_;
};

int open_terminos(const char *tty_name) { return open_via_terminos(tty_name); }

std::string GetFileContents(const std::string &filename) {
  std::ifstream in(filename, std::ios::in | std::ios::binary);
  if (in) {
    std::string contents;
    in.seekg(0, std::ios::end);
    contents.resize(in.tellg());
    in.seekg(0, std::ios::beg);
    in.read(&contents[0], contents.size());
    in.close();
    return (contents);
  }
  fprintf(stderr, "Could not read file: %s\n", filename.c_str());
  exit(-1);
}

using aos::vision::ImageFormat;
using aos::vision::ImageRange;
using aos::vision::RangeImage;
using y2019::vision::IntermediateResult;
using y2019::vision::Target;
using y2019::vision::TargetFinder;

class TargetProcessPool {
 public:
  // The number of threads we'll use.
  static constexpr int kThreads = 4;

  TargetProcessPool(TargetFinder *finder);
  ~TargetProcessPool();

  std::vector<IntermediateResult> Process(std::vector<const Target *> &&inputs,
                                          bool verbose);

 private:
  // The main function for a thread.
  void RunThread();

  std::array<std::thread, kThreads> threads_;
  // Coordinates access to results_/inputs_ and coordinates with
  // condition_variable_.
  std::mutex mutex_;
  // Signals changes to results_/inputs_ and quit_.
  std::condition_variable condition_variable_;
  bool quit_ = false;

  bool verbose_ = false;
  std::vector<const Target *> inputs_;
  std::vector<IntermediateResult> results_;

  TargetFinder *const finder_;
};

TargetProcessPool::TargetProcessPool(TargetFinder *finder) : finder_(finder) {
  for (int i = 0; i < kThreads; ++i) {
    threads_[i] = std::thread([this]() { RunThread(); });
  }
}

TargetProcessPool::~TargetProcessPool() {
  {
    std::unique_lock<std::mutex> locker(mutex_);
    quit_ = true;
    condition_variable_.notify_all();
  }
  for (int i = 0; i < kThreads; ++i) {
    threads_[i].join();
  }
}

std::vector<IntermediateResult> TargetProcessPool::Process(
    std::vector<const Target *> &&inputs, bool verbose) {
  inputs_ = std::move(inputs);
  results_.clear();
  verbose_ = verbose;
  const size_t number_targets = inputs_.size();
  {
    std::unique_lock<std::mutex> locker(mutex_);
    condition_variable_.notify_all();
    while (results_.size() < number_targets) {
      condition_variable_.wait(locker);
    }
  }
  return std::move(results_);
}

void TargetProcessPool::RunThread() {
  while (true) {
    const Target *my_input;
    {
      std::unique_lock<std::mutex> locker(mutex_);
      while (inputs_.empty()) {
        if (quit_) {
          return;
        }
        condition_variable_.wait(locker);
      }
      my_input = inputs_.back();
      inputs_.pop_back();
    }
    IntermediateResult my_output =
        finder_->ProcessTargetToResult(*my_input, false);
    {
      std::unique_lock<std::mutex> locker(mutex_);
      results_.emplace_back(std::move(my_output));
      condition_variable_.notify_all();
    }
  }
}

int main(int argc, char **argv) {
  (void)argc;
  (void)argv;
  using namespace y2019::vision;
  using frc971::jevois::CameraCommand;
  // gflags::ParseCommandLineFlags(&argc, &argv, false);
  FLAGS_logtostderr = true;
  google::InitGoogleLogging(argv[0]);

  int itsDev = open_terminos("/dev/ttyS0");
  frc971::jevois::CobsPacketizer<frc971::jevois::uart_to_camera_size()> cobs;
  // Uncomment these to printf directly to stdout to get debug info...
  // dup2(itsDev, 1);
  // dup2(itsDev, 2);

  TargetFinder finder;
  TargetProcessPool process_pool(&finder);
  ImageWriter writer;
  uint32_t image_count = 0;
  bool log_images = false;

  aos::vision::CameraParams params0;
  params0.set_exposure(60);
  params0.set_brightness(40);
  params0.set_width(640);
  params0.set_fps(25);
  params0.set_height(480);

  aos::vision::FastYuyvYPooledThresholder thresholder;

  // A source of psuedorandom numbers which gives different numbers each time we
  // need to drop targets.
  std::minstd_rand random_engine;

  ::std::unique_ptr<CameraStream> camera0(
      new CameraStream(params0, "/dev/video0"));
  camera0->set_on_frame([&](DataRef data,
                            monotonic_clock::time_point monotonic_now) {
    aos::vision::ImageFormat fmt{640, 480};
    aos::vision::BlobList imgs =
        aos::vision::FindBlobs(thresholder.Threshold(fmt, data.data(), 120));
    const int num_pixels = finder.PixelCount(&imgs);
    LOG(INFO) << "Number pixels: " << num_pixels;
    finder.PreFilter(&imgs);
    LOG(INFO) << "Blobs: " << imgs.size();

    constexpr bool verbose = false;
    ::std::vector<Polygon> raw_polys;
    for (const RangeImage &blob : imgs) {
      // Convert blobs to contours in the corrected space.
      ContourNode *contour = finder.GetContour(blob);
      ::std::vector<::Eigen::Vector2f> unwarped_contour =
          finder.UnWarpContour(contour);
      const Polygon polygon =
          finder.FindPolygon(::std::move(unwarped_contour), verbose);
      if (!polygon.segments.empty()) {
        raw_polys.push_back(polygon);
      }
    }
    LOG(INFO) << "Polygons: " << raw_polys.size();

    // Calculate each component side of a possible target.
    ::std::vector<TargetComponent> target_component_list =
        finder.FillTargetComponentList(raw_polys, verbose);
    LOG(INFO) << "Components: " << target_component_list.size();

    // Put the compenents together into targets.
    ::std::vector<Target> target_list =
        finder.FindTargetsFromComponents(target_component_list, verbose);
    static constexpr size_t kMaximumPotentialTargets = 8;
    LOG(INFO) << "Potential Targets (will filter to "
              << kMaximumPotentialTargets << "): " << target_list.size();

    // A list of all the indices into target_list which we're going to actually
    // use.
    std::vector<int> target_list_indices;
    target_list_indices.resize(target_list.size());
    for (size_t i = 0; i < target_list.size(); ++i) {
      target_list_indices[i] = i;
    }
    // Drop random elements until we get sufficiently few of them. We drop
    // different elements each time to ensure we will see different valid
    // targets on successive frames, which provides more useful information to
    // the localization.
    while (target_list_indices.size() > kMaximumPotentialTargets) {
      std::uniform_int_distribution<size_t> distribution(
          0, target_list_indices.size() - 1);
      const size_t index = distribution(random_engine);
      target_list_indices.erase(target_list_indices.begin() + index);
    }

    // Use the solver to generate an intermediate version of our results.
    std::vector<const Target *> inputs;
    for (size_t index : target_list_indices) {
      inputs.push_back(&target_list[index]);
    }
    std::vector<IntermediateResult> results =
        process_pool.Process(std::move(inputs), verbose);
    LOG(INFO) << "Raw Results: " << results.size();

    results = finder.FilterResults(results, 30, verbose);
    LOG(INFO) << "Results: " << results.size();

    int desired_exposure;
    if (finder.TestExposure(results, num_pixels, &desired_exposure)) {
      camera0->SetExposure(desired_exposure);
    }

    frc971::jevois::CameraFrame frame{};

    for (size_t i = 0; i < results.size() && i < frame.targets.capacity();
         ++i) {
      const auto &result = results[i].extrinsics;
      frame.targets.push_back(frc971::jevois::Target{
          static_cast<float>(result.z), static_cast<float>(result.y),
          static_cast<float>(result.r2), static_cast<float>(result.r1)});
    }

    frame.age = std::chrono::duration_cast<frc971::jevois::camera_duration>(
        aos::monotonic_clock::now() - monotonic_now);

    // If we succeed in writing our delimiter, then write out the rest of
    // the frame. If not, no point in continuing.
    if (write(itsDev, "\0", 1) == 1) {
      const auto serialized_frame = frc971::jevois::UartPackToTeensy(frame);
      // We don't really care if this succeeds or not. If it fails for some
      // reason, we'll just try again with the next frame, and the other end
      // will find the new packet just fine.
      ssize_t n =
          write(itsDev, serialized_frame.data(), serialized_frame.size());

      if (n != (ssize_t)serialized_frame.size()) {
        LOG(INFO) << "Some problem happened";
      }
    }

    if (log_images) {
      if ((image_count % 5) == 0) {
        writer.WriteImage(data);
      }
      ++image_count;
    }
  });

  aos::events::EpollLoop loop;

  while (true) {
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
    camera0->ReadEvent();

    {
      constexpr size_t kBufferSize = frc971::jevois::uart_to_teensy_size();
      char data[kBufferSize];
      ssize_t n = read(itsDev, &data[0], kBufferSize);
      if (n >= 1) {
        cobs.ParseData(absl::Span<const char>(&data[0], n));
        auto packet = cobs.received_packet();
        if (!packet.empty()) {
          auto calibration_question =
              frc971::jevois::UartUnpackToCamera(packet);
          if (calibration_question) {
            const auto &calibration = *calibration_question;
            IntrinsicParams *intrinsics = finder.mutable_intrinsics();
            intrinsics->mount_angle = calibration.calibration(0, 0);
            intrinsics->focal_length = calibration.calibration(0, 1);
            intrinsics->barrel_mount = calibration.calibration(0, 2);

            switch (calibration.camera_command) {
              case CameraCommand::kNormal:
              case CameraCommand::kAs:
                log_images = false;
                break;
              case CameraCommand::kLog:
                log_images = true;
                break;
              case CameraCommand::kUsb:
                return 0;
              case CameraCommand::kCameraPassthrough:
                return system("touch /tmp/do_not_export_sd_card");
            }
          } else {
            fprintf(stderr, "bad frame\n");
          }
          cobs.clear_received_packet();
        }
      }
    }
  }

  // TODO: Fix event loop on jevois:
  // loop.Add(camera0.get());
  // loop.Run();
}
