/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>

#include <adf/adf.h>
#include <sync/sync.h>

#include "graphics.h"

struct adf_surface_pdata {
  GRSurface base;
  int fence_fd;
  int fd;
  __u32 offset;
  __u32 pitch;
};

struct adf_pdata {
  minui_backend base;
  int intf_fd;
  adf_id_t eng_id;
  __u32 format;

  adf_device dev;

  unsigned int current_surface;
  unsigned int n_surfaces;
  adf_surface_pdata surfaces[2];
};

static GRSurface* adf_flip(minui_backend* backend);
static void adf_blank(minui_backend* backend, bool blank);

static int adf_surface_init(adf_pdata* pdata, drm_mode_modeinfo* mode, adf_surface_pdata* surf) {
  *surf = {};
  surf->fence_fd = -1;
  surf->fd = adf_interface_simple_buffer_alloc(pdata->intf_fd, mode->hdisplay, mode->vdisplay,
                                               pdata->format, &surf->offset, &surf->pitch);
  if (surf->fd < 0) {
    return surf->fd;
  }

  surf->base.width = mode->hdisplay;
  surf->base.height = mode->vdisplay;
  surf->base.row_bytes = surf->pitch;
  surf->base.pixel_bytes = (pdata->format == DRM_FORMAT_RGB565) ? 2 : 4;

  surf->base.data = static_cast<uint8_t*>(mmap(nullptr, surf->pitch * surf->base.height, PROT_WRITE,
                                               MAP_SHARED, surf->fd, surf->offset));
  if (surf->base.data == MAP_FAILED) {
    close(surf->fd);
    return -errno;
  }

  return 0;
}

static int adf_interface_init(adf_pdata* pdata) {
  adf_interface_data intf_data;
  int err = adf_get_interface_data(pdata->intf_fd, &intf_data);
  if (err < 0) return err;

  int ret = 0;
  err = adf_surface_init(pdata, &intf_data.current_mode, &pdata->surfaces[0]);
  if (err < 0) {
    fprintf(stderr, "allocating surface 0 failed: %s\n", strerror(-err));
    ret = err;
    goto done;
  }

  err = adf_surface_init(pdata, &intf_data.current_mode, &pdata->surfaces[1]);
  if (err < 0) {
    fprintf(stderr, "allocating surface 1 failed: %s\n", strerror(-err));
    pdata->surfaces[1] = {};
    pdata->n_surfaces = 1;
  } else {
    pdata->n_surfaces = 2;
  }

done:
  adf_free_interface_data(&intf_data);
  return ret;
}

static int adf_device_init(adf_pdata* pdata, adf_device* dev) {
  adf_id_t intf_id;
  int err = adf_find_simple_post_configuration(dev, &pdata->format, 1, &intf_id, &pdata->eng_id);
  if (err < 0) return err;

  err = adf_device_attach(dev, pdata->eng_id, intf_id);
  if (err < 0 && err != -EALREADY) return err;

  pdata->intf_fd = adf_interface_open(dev, intf_id, O_RDWR);
  if (pdata->intf_fd < 0) return pdata->intf_fd;

  err = adf_interface_init(pdata);
  if (err < 0) {
    close(pdata->intf_fd);
    pdata->intf_fd = -1;
  }

  return err;
}

static GRSurface* adf_init(minui_backend* backend) {
  adf_pdata* pdata = reinterpret_cast<adf_pdata*>(backend);

#if defined(RECOVERY_ABGR)
  pdata->format = DRM_FORMAT_ABGR8888;
#elif defined(RECOVERY_BGRA)
  pdata->format = DRM_FORMAT_BGRA8888;
#elif defined(RECOVERY_RGBX)
  pdata->format = DRM_FORMAT_RGBX8888;
#else
  pdata->format = DRM_FORMAT_RGB565;
#endif

  adf_id_t* dev_ids = nullptr;
  ssize_t n_dev_ids = adf_devices(&dev_ids);
  if (n_dev_ids == 0) {
    return nullptr;
  } else if (n_dev_ids < 0) {
    fprintf(stderr, "enumerating adf devices failed: %s\n", strerror(-n_dev_ids));
    return nullptr;
  }

  pdata->intf_fd = -1;

  for (ssize_t i = 0; i < n_dev_ids && pdata->intf_fd < 0; i++) {
    int err = adf_device_open(dev_ids[i], O_RDWR, &pdata->dev);
    if (err < 0) {
      fprintf(stderr, "opening adf device %u failed: %s\n", dev_ids[i], strerror(-err));
      continue;
    }

    err = adf_device_init(pdata, &pdata->dev);
    if (err < 0) {
      fprintf(stderr, "initializing adf device %u failed: %s\n", dev_ids[i], strerror(-err));
      adf_device_close(&pdata->dev);
    }
  }

  free(dev_ids);

  if (pdata->intf_fd < 0) return nullptr;

  GRSurface* ret = adf_flip(backend);

  adf_blank(backend, true);
  adf_blank(backend, false);

  return ret;
}

static void adf_sync(adf_surface_pdata* surf) {
  static constexpr unsigned int warningTimeout = 3000;

  if (surf == nullptr) return;

  if (surf->fence_fd >= 0) {
    int err = sync_wait(surf->fence_fd, warningTimeout);
    if (err < 0) {
      perror("adf sync fence wait error\n");
    }

    close(surf->fence_fd);
    surf->fence_fd = -1;
  }
}

static GRSurface* adf_flip(minui_backend* backend) {
  adf_pdata* pdata = reinterpret_cast<adf_pdata*>(backend);
  adf_surface_pdata* surf = &pdata->surfaces[pdata->current_surface];

  int fence_fd =
      adf_interface_simple_post(pdata->intf_fd, pdata->eng_id, surf->base.width, surf->base.height,
                                pdata->format, surf->fd, surf->offset, surf->pitch, -1);
  if (fence_fd >= 0) surf->fence_fd = fence_fd;

  pdata->current_surface = (pdata->current_surface + 1) % pdata->n_surfaces;
  adf_sync(&pdata->surfaces[pdata->current_surface]);
  return &pdata->surfaces[pdata->current_surface].base;
}

static void adf_blank(minui_backend* backend, bool blank) {
  adf_pdata* pdata = reinterpret_cast<adf_pdata*>(backend);
  adf_interface_blank(pdata->intf_fd, blank ? DRM_MODE_DPMS_OFF : DRM_MODE_DPMS_ON);
}

static void adf_surface_destroy(adf_surface_pdata* surf) {
  munmap(surf->base.data, surf->pitch * surf->base.height);
  close(surf->fence_fd);
  close(surf->fd);
}

static void adf_exit(minui_backend* backend) {
  adf_pdata* pdata = reinterpret_cast<adf_pdata*>(backend);
  adf_device_close(&pdata->dev);
  for (unsigned int i = 0; i < pdata->n_surfaces; i++) {
    adf_surface_destroy(&pdata->surfaces[i]);
  }
  if (pdata->intf_fd >= 0) close(pdata->intf_fd);
  free(pdata);
}

minui_backend* open_adf() {
  adf_pdata* pdata = static_cast<adf_pdata*>(calloc(1, sizeof(*pdata)));
  if (!pdata) {
    perror("allocating adf backend failed");
    return nullptr;
  }

  pdata->base.init = adf_init;
  pdata->base.flip = adf_flip;
  pdata->base.blank = adf_blank;
  pdata->base.exit = adf_exit;

  return &pdata->base;
}
