/*
 * Copyright (C) 2007 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.
 */

#pragma once

#include <stdint.h>
#include <stdlib.h>
#include <sys/types.h>

#include <functional>
#include <memory>
#include <string>
#include <vector>

#include <android-base/macros.h>
#include <android-base/unique_fd.h>

//
// Graphics.
//

class GRSurface {
 public:
  static constexpr size_t kSurfaceDataAlignment = 8;

  virtual ~GRSurface() = default;

  // Creates and returns a GRSurface instance that's sufficient for storing an image of the given
  // size (i.e. row_bytes * height). The starting address of the surface data is aligned to
  // kSurfaceDataAlignment. Returns the created GRSurface instance (in std::unique_ptr), or nullptr
  // on error.
  static std::unique_ptr<GRSurface> Create(size_t width, size_t height, size_t row_bytes,
                                           size_t pixel_bytes);

  // Clones the current GRSurface instance (i.e. an image).
  std::unique_ptr<GRSurface> Clone() const;

  virtual uint8_t* data() {
    return data_.get();
  }

  const uint8_t* data() const {
    return const_cast<const uint8_t*>(const_cast<GRSurface*>(this)->data());
  }

  size_t data_size() const {
    return data_size_;
  }

  size_t width;
  size_t height;
  size_t row_bytes;
  size_t pixel_bytes;

 protected:
  GRSurface(size_t width, size_t height, size_t row_bytes, size_t pixel_bytes)
      : width(width), height(height), row_bytes(row_bytes), pixel_bytes(pixel_bytes) {}

 private:
  // The deleter for data_, whose data is allocated via aligned_alloc(3).
  struct DataDeleter {
    void operator()(uint8_t* data) {
      free(data);
    }
  };

  std::unique_ptr<uint8_t, DataDeleter> data_;
  size_t data_size_;

  DISALLOW_COPY_AND_ASSIGN(GRSurface);
};

struct GRFont {
  GRSurface* texture;
  int char_width;
  int char_height;
};

enum class GRRotation : int {
  NONE = 0,
  RIGHT = 1,
  DOWN = 2,
  LEFT = 3,
};

enum class PixelFormat : int {
  UNKNOWN = 0,
  ABGR = 1,
  RGBX = 2,
  BGRA = 3,
  ARGB = 4,
};

enum class GraphicsBackend : int {
  UNKNOWN = 0,
  DRM = 1,
  FBDEV = 2,
};

// Initializes the default graphics backend and loads font file. Returns 0 on success, or -1 on
// error. Note that the font initialization failure would be non-fatal, as caller may not need to
// draw any text at all. Caller can check the font initialization result via gr_sys_font() as
// needed.
int gr_init();
// Supports backend selection for minui client.
int gr_init(std::initializer_list<GraphicsBackend> backends);

// Frees the allocated resources. The function is idempotent, and safe to be called if gr_init()
// didn't finish successfully.
void gr_exit();

int gr_fb_width();
int gr_fb_height();

void gr_flip();
void gr_fb_blank(bool blank);
void gr_fb_blank(bool blank, int index);

// Clears entire surface to current color.
void gr_clear();
void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
void gr_fill(int x1, int y1, int x2, int y2);

void gr_texticon(int x, int y, const GRSurface* icon);

const GRFont* gr_sys_font();
int gr_init_font(const char* name, GRFont** dest);
void gr_text(const GRFont* font, int x, int y, const char* s, bool bold);
// Returns -1 if font is nullptr.
int gr_measure(const GRFont* font, const char* s);
// Returns -1 if font is nullptr.
int gr_font_size(const GRFont* font, int* x, int* y);

void gr_blit(const GRSurface* source, int sx, int sy, int w, int h, int dx, int dy);
unsigned int gr_get_width(const GRSurface* surface);
unsigned int gr_get_height(const GRSurface* surface);

// Sets rotation, flips gr_fb_width/height if 90 degree rotation difference
void gr_rotate(GRRotation rotation);

// Returns the current PixelFormat being used.
PixelFormat gr_pixel_format();

//
// Input events.
//

struct input_event;

using ev_callback = std::function<int(int fd, uint32_t epevents)>;
using ev_set_key_callback = std::function<int(int code, int value)>;
using ev_set_sw_callback = std::function<int(int code, int value)>;

int ev_init(ev_callback input_cb, bool allow_touch_inputs = false);
void ev_exit();
int ev_add_fd(android::base::unique_fd&& fd, ev_callback cb);
void ev_iterate_available_keys(const std::function<void(int)>& f);
void ev_iterate_touch_inputs(const std::function<void(int)>& action);
int ev_sync_key_state(const ev_set_key_callback& set_key_cb);
int ev_sync_sw_state(const ev_set_sw_callback& set_sw_cb);

// 'timeout' has the same semantics as poll(2).
//    0 : don't block
//  < 0 : block forever
//  > 0 : block for 'timeout' milliseconds
int ev_wait(int timeout);

int ev_get_input(int fd, uint32_t epevents, input_event* ev);
void ev_dispatch();
int ev_get_epollfd();

//
// Resources
//

bool matches_locale(const std::string& prefix, const std::string& locale);

// res_create_*_surface() functions return 0 if no error, else
// negative.
//
// A "display" surface is one that is intended to be drawn to the
// screen with gr_blit().  An "alpha" surface is a grayscale image
// interpreted as an alpha mask used to render text in the current
// color (with gr_text() or gr_texticon()).
//
// All these functions load PNG images from "/res/images/${name}.png".

// Load a single display surface from a PNG image.
int res_create_display_surface(const char* name, GRSurface** pSurface);

// Load an array of display surfaces from a single PNG image.  The PNG
// should have a 'Frames' text chunk whose value is the number of
// frames this image represents.  The pixel data itself is interlaced
// by row.
int res_create_multi_display_surface(const char* name, int* frames, int* fps,
                                     GRSurface*** pSurface);

// Load a single alpha surface from a grayscale PNG image.
int res_create_alpha_surface(const char* name, GRSurface** pSurface);

// Load part of a grayscale PNG image that is the first match for the
// given locale.  The image is expected to be a composite of multiple
// translations of the same text, with special added rows that encode
// the subimages' size and intended locale in the pixel data.  See
// bootable/recovery/tools/recovery_l10n for an app that will generate
// these specialized images from Android resources.
int res_create_localized_alpha_surface(const char* name, const char* locale,
                                       GRSurface** pSurface);

// Return a list of locale strings embedded in |png_name|. Return a empty list in case of failure.
std::vector<std::string> get_locales_in_png(const std::string& png_name);

// Free a surface allocated by any of the res_create_*_surface()
// functions.
void res_free_surface(GRSurface* surface);
