// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <assert.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <fuchsia/input/report/cpp/fidl.h>
#include <lib/ddk/device.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/unsafe.h>
#include <lib/framebuffer/framebuffer.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <zircon/process.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

#include <fbl/unique_fd.h>

namespace simple_touch {

namespace fidl_report = ::fuchsia::input::report;

typedef struct display_info {
  uint32_t width;
  uint32_t height;
  uint32_t stride;
  zx_pixel_format_t format;
} display_info_t;

// This class manages the framebuffer. It will initialize the buffer, draw to it,
// and flush it back to memory.
// At the moment we only support a single buffer with a pixel size of 32 byes and
// a color format of RGBA.
class FrameBuffer {
 public:
  ~FrameBuffer();
  zx_status_t Init();
  // Draw a square point centered at |x| and |y| with |width| and |height|.
  void DrawPoint(uint32_t color, uint32_t x, uint32_t y, uint8_t width, uint8_t height);
  void FlushScreen() { zx_cache_flush(pixels_, pixels_size_, ZX_CACHE_FLUSH_DATA); }
  void ClearScreen();
  display_info_t DisplayInfo() { return display_info_; }

 private:
  display_info_t display_info_ = {};
  uint32_t* pixels_ = nullptr;
  size_t pixels_size_ = 0;
};

FrameBuffer::~FrameBuffer() {
  if (pixels_) {
    _zx_vmar_unmap(zx_vmar_root_self(), reinterpret_cast<zx_vaddr_t>(pixels_), pixels_size_);
  }
  fb_release();
}

zx_status_t FrameBuffer::Init() {
  const char* err;
  zx_status_t status = fb_bind(true, &err);
  if (status != ZX_OK) {
    printf("failed to open framebuffer: %d (%s)\n", status, err);
    return status;
  }
  display_info_t info;
  fb_get_config(&info.width, &info.height, &info.stride, &info.format);

  zx_handle_t vmo = fb_get_single_buffer();

  printf("format = %d\n", info.format);
  printf("width = %d\n", info.width);
  printf("height = %d\n", info.height);
  printf("stride = %d\n", info.stride);

  pixels_size_ = info.stride * ZX_PIXEL_FORMAT_BYTES(info.format) * info.height;
  uintptr_t frame_buffer_ptr;
  status = zx_vmar_map(zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0, vmo, 0,
                       pixels_size_, &frame_buffer_ptr);
  if (status != ZX_OK) {
    return status;
  }

  pixels_ = (uint32_t*)frame_buffer_ptr;
  display_info_ = info;

  ClearScreen();
  FlushScreen();
  return ZX_OK;
}

void FrameBuffer::DrawPoint(uint32_t color, uint32_t x, uint32_t y, uint8_t width, uint8_t height) {
  uint32_t fb_width = display_info_.stride;
  uint32_t fb_height = display_info_.height;
  uint32_t xrad = (width + 1) / 2;
  uint32_t yrad = (height + 1) / 2;

  uint32_t xmin = (xrad > x) ? 0 : x - xrad;
  uint32_t xmax = (xrad > fb_width - x) ? fb_width : x + xrad;
  uint32_t ymin = (yrad > y) ? 0 : y - yrad;
  uint32_t ymax = (yrad > fb_height - y) ? fb_height : y + yrad;

  for (uint32_t px = xmin; px < xmax; px++) {
    for (uint32_t py = ymin; py < ymax; py++) {
      *(pixels_ + py * fb_width + px) = color;
    }
  }
}

void FrameBuffer::ClearScreen() { memset(pixels_, 0xff, pixels_size_); }

// This class sits over the framebuffer and is responsible for associating touches with color,
// for drawing the clear and exit button, and for recognizing button touches.
class TouchApp {
 public:
  zx_status_t Init() {
    zx_status_t status = frame_buffer_.Init();
    if (status != ZX_OK) {
      return status;
    }
    display_info_ = frame_buffer_.DisplayInfo();

    ClearScreen();
    FlushScreen();

    status = GetTouchScreen();
    if (status != ZX_OK) {
      return status;
    }

    return ZX_OK;
  }

  void ClearScreen() {
    frame_buffer_.ClearScreen();
    frame_buffer_.DrawPoint(0xff00ff, display_info_.stride - (kButtonSize / 2), (kButtonSize / 2),
                            kButtonSize, kButtonSize);
    frame_buffer_.DrawPoint(0x0000ff, (kButtonSize / 2), display_info_.height - (kButtonSize / 2),
                            kButtonSize, kButtonSize);
  }

  void FlushScreen() { frame_buffer_.FlushScreen(); }

  void DrawPoint(uint32_t color, uint32_t x, uint32_t y, uint8_t width, uint8_t height) {
    x = x * display_info_.width / max_x_;
    y = y * display_info_.height / max_y_;
    frame_buffer_.DrawPoint(color, x, y, width, height);

    if (x + kButtonSize > display_info_.width && y < kButtonSize) {
      ClearScreen();
      FlushScreen();
    }
    if (((y + kButtonSize) > display_info_.height) && (x < kButtonSize)) {
      run_ = false;
    }
  }

  void SetMaxValues(uint32_t x, uint32_t y) {
    max_x_ = x;
    max_y_ = y;
  }

  int Run() {
    fidl_report::InputReportsReaderSyncPtr reader;
    client_->GetInputReportsReader(reader.NewRequest());

    zx_status_t status;
    run_ = true;
    while (run_) {
      // Get the report.
      fidl_report::InputReportsReader_ReadInputReports_Result result;
      status = reader->ReadInputReports(&result);
      if (status != ZX_OK) {
        printf("GetReports FIDL call returned %s\n", zx_status_get_string(status));
        return 1;
      }
      if (result.is_err()) {
        printf("GetReports FIDL result returned %s\n", zx_status_get_string(result.err()));
        return 1;
      }

      for (auto& report : result.response().reports) {
        if (!report.has_touch()) {
          continue;
        }
        if (!report.touch().has_contacts()) {
          continue;
        }
        for (size_t i = 0; i < report.touch().contacts().size(); i++) {
          uint32_t x = report.touch().contacts()[i].position_x();
          uint32_t y = report.touch().contacts()[i].position_y();
          uint32_t contact_id = report.touch().contacts()[i].contact_id();
          uint32_t width = 10;
          uint32_t height = 10;
          DrawPoint(kColors[contact_id % kColors.size()], x, y, width, height);
        }
      }
      FlushScreen();
    }
    return 0;
  }

 private:
  static constexpr uint32_t kButtonSize = 50;
  // Array of colors for each finger
  static constexpr std::array<uint32_t, 10> kColors = {
      0x00ff0000, 0x0000ff00, 0x000000ff, 0x00ffff00, 0x00ff00ff,
      0x0000ffff, 0x00000000, 0x00f0f0f0, 0x00f00f00, 0x000ff000,
  };

  // Gets the touch client from a file path. Sets |client_| on success.
  zx_status_t GetClientFromFilePath(const char* path) {
    fbl::unique_fd fd(open(path, O_RDWR));
    if (!fd.is_valid()) {
      return ZX_ERR_INTERNAL;
    }

    zx::channel chan;
    zx_status_t status = fdio_get_service_handle(fd.release(), chan.reset_and_get_address());
    if (status != ZX_OK) {
      printf("Ftdio get handle failed with %s\n", zx_status_get_string(status));
      return status;
    }
    client_.Bind(std::move(chan));
    return ZX_OK;
  }

  bool IsTouchscreen(const fidl_report::DeviceDescriptor& descriptor) {
    if (!descriptor.has_touch() || !descriptor.touch().has_input()) {
      return false;
    }
    const fidl_report::TouchInputDescriptor& touch_desc = descriptor.touch().input();
    if (!touch_desc.has_touch_type() ||
        (touch_desc.touch_type() != fidl_report::TouchType::TOUCHSCREEN)) {
      return false;
    }
    return true;
  }

  // Iterates through the input-report directory and finds a touchscreen.
  // Gets that touchscreen's client and report event.
  zx_status_t GetTouchScreen() {
    // Find the touchscreen.
    struct dirent* de;
    DIR* dir = opendir("/dev/class/input-report");
    if (!dir) {
      printf("failed to open %s: %d\n", "/dev/class/input-report", errno);
      return ZX_ERR_INTERNAL;
    }

    while ((de = readdir(dir)) != NULL) {
      char devname[128];

      if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
        continue;
      }

      // Get the |client_| from the path.
      snprintf(devname, sizeof(devname), "%s/%s", "/dev/class/input-report", de->d_name);
      zx_status_t status = GetClientFromFilePath(devname);

      // Get the DeviceDescriptor.
      fidl_report::DeviceDescriptor device_descriptor;
      status = client_->GetDescriptor(&device_descriptor);
      if (status != ZX_OK) {
        printf("GetDescriptor FIDL call returned %s\n", zx_status_get_string(status));
        return status;
      }

      if (!IsTouchscreen(device_descriptor)) {
        continue;
      }

      SetMaxValues(device_descriptor.touch().input().contacts()[0].position_x().range.max,
                   device_descriptor.touch().input().contacts()[0].position_y().range.max);

      printf("Found touchscreen at %s\n", devname);
      return ZX_OK;
    }

    return ZX_ERR_NOT_FOUND;
  }

  uint32_t max_x_ = 0;
  uint32_t max_y_ = 0;
  fidl_report::InputDeviceSyncPtr client_;
  FrameBuffer frame_buffer_;
  display_info_t display_info_ = {};
  bool run_ = true;
};

}  // namespace simple_touch

int main(int argc, char* argv[]) {
  simple_touch::TouchApp app;
  zx_status_t status = app.Init();
  if (status != ZX_OK) {
    return 1;
  }

  return app.Run();
}
