#ifndef APP_OPENGL_H
#define APP_OPENGL_H
typedef enum app_interpolation_t {
  APP_INTERPOLATION_NONE,
  APP_INTERPOLATION_LINEAR,
} app_interpolation_t;
#ifndef APP_NULL
#if defined(APP_WINDOWS)

#define _CRT_NONSTDC_NO_DEPRECATE
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stddef.h>
#define APP_GLCALLTYPE __stdcall
typedef unsigned int APP_GLuint;
typedef int APP_GLsizei;
typedef unsigned int APP_GLenum;
typedef int APP_GLint;
typedef float APP_GLfloat;
typedef char APP_GLchar;
typedef unsigned char APP_GLboolean;
typedef size_t APP_GLsizeiptr;
typedef unsigned int APP_GLbitfield;

#define APP_GL_FLOAT 0x1406
#define APP_GL_FALSE 0
#define APP_GL_FRAGMENT_SHADER 0x8b30
#define APP_GL_VERTEX_SHADER 0x8b31
#define APP_GL_COMPILE_STATUS 0x8b81
#define APP_GL_LINK_STATUS 0x8b82
#define APP_GL_INFO_LOG_LENGTH 0x8b84
#define APP_GL_ARRAY_BUFFER 0x8892
#define APP_GL_TEXTURE_2D 0x0de1
#define APP_GL_TEXTURE0 0x84c0
#define APP_GL_CLAMP 0x2900
#define APP_GL_TEXTURE_WRAP_S 0x2802
#define APP_GL_TEXTURE_WRAP_T 0x2803
#define APP_GL_TEXTURE_MIN_FILTER 0x2801
#define APP_GL_TEXTURE_MAG_FILTER 0x2800
#define APP_GL_NEAREST 0x2600
#define APP_GL_LINEAR 0x2601
#define APP_GL_STATIC_DRAW 0x88e4
#define APP_GL_RGBA 0x1908
#define APP_GL_UNSIGNED_BYTE 0x1401
#define APP_GL_COLOR_BUFFER_BIT 0x00004000
#define APP_GL_TRIANGLE_FAN 0x0006

#elif defined(APP_SDL) || defined(APP_WASM)

#if defined(APP_WASM)
#include <wajic_gl.h>
#define WA_CORO_IMPLEMENT_NANOSLEEP
#include <wajic_coro.h>
#else
#include "SDL_opengl.h"
#include <GL/glew.h>
#endif
#define APP_GLCALLTYPE GLAPIENTRY
typedef GLuint APP_GLuint;
typedef GLsizei APP_GLsizei;
typedef GLenum APP_GLenum;
typedef GLint APP_GLint;
typedef GLfloat APP_GLfloat;
typedef GLchar APP_GLchar;
typedef GLboolean APP_GLboolean;
typedef GLsizeiptr APP_GLsizeiptr;
typedef GLbitfield APP_GLbitfield;

#define APP_GL_FLOAT GL_FLOAT
#define APP_GL_FALSE GL_FALSE
#define APP_GL_FRAGMENT_SHADER GL_FRAGMENT_SHADER
#define APP_GL_VERTEX_SHADER GL_VERTEX_SHADER
#define APP_GL_COMPILE_STATUS GL_COMPILE_STATUS
#define APP_GL_LINK_STATUS GL_LINK_STATUS
#define APP_GL_INFO_LOG_LENGTH GL_INFO_LOG_LENGTH
#define APP_GL_ARRAY_BUFFER GL_ARRAY_BUFFER
#define APP_GL_TEXTURE_2D GL_TEXTURE_2D
#define APP_GL_TEXTURE0 GL_TEXTURE0
#if defined(APP_WASM)
#define APP_GL_CLAMP GL_CLAMP_TO_EDGE
#else
#define APP_GL_CLAMP GL_CLAMP
#endif
#define APP_GL_TEXTURE_WRAP_S GL_TEXTURE_WRAP_S
#define APP_GL_TEXTURE_WRAP_T GL_TEXTURE_WRAP_T
#define APP_GL_TEXTURE_MIN_FILTER GL_TEXTURE_MIN_FILTER
#define APP_GL_TEXTURE_MAG_FILTER GL_TEXTURE_MAG_FILTER
#define APP_GL_NEAREST GL_NEAREST
#define APP_GL_LINEAR GL_LINEAR
#define APP_GL_STATIC_DRAW GL_STATIC_DRAW
#define APP_GL_RGBA GL_RGBA
#define APP_GL_UNSIGNED_BYTE GL_UNSIGNED_BYTE
#define APP_GL_COLOR_BUFFER_BIT GL_COLOR_BUFFER_BIT
#define APP_GL_TRIANGLE_FAN GL_TRIANGLE_FAN

#else

#error Undefined platform. Define APP_WINDOWS, APP_SDL, APP_WASM or APP_NULL.
#define APP_GLCALLTYPE
typedef int APP_GLuint;
typedef int APP_GLsizei;
typedef int APP_GLenum;
typedef int APP_GLint;
typedef int APP_GLfloat;
typedef int APP_GLchar;
typedef int APP_GLboolean;
typedef int APP_GLsizeiptr;
typedef int APP_GLbitfield;

#endif
#endif

#ifdef APP_REPORT_SHADER_ERRORS
#include <string.h>
#endif

struct app_internal_opengl_t {

  APP_GLuint(APP_GLCALLTYPE *CreateShader)(APP_GLenum type);
  void(APP_GLCALLTYPE *ShaderSource)(APP_GLuint shader, APP_GLsizei count,
                                     APP_GLchar const *const *string,
                                     APP_GLint const *length);
  void(APP_GLCALLTYPE *CompileShader)(APP_GLuint shader);
  void(APP_GLCALLTYPE *GetShaderiv)(APP_GLuint shader, APP_GLenum pname,
                                    APP_GLint *params);
  APP_GLuint(APP_GLCALLTYPE *CreateProgram)(void);
  void(APP_GLCALLTYPE *AttachShader)(APP_GLuint program, APP_GLuint shader);
  void(APP_GLCALLTYPE *BindAttribLocation)(APP_GLuint program, APP_GLuint index,
                                           APP_GLchar const *name);
  void(APP_GLCALLTYPE *LinkProgram)(APP_GLuint program);
  void(APP_GLCALLTYPE *GetProgramiv)(APP_GLuint program, APP_GLenum pname,
                                     APP_GLint *params);
  void(APP_GLCALLTYPE *GenBuffers)(APP_GLsizei n, APP_GLuint *buffers);
  void(APP_GLCALLTYPE *BindBuffer)(APP_GLenum target, APP_GLuint buffer);
  void(APP_GLCALLTYPE *EnableVertexAttribArray)(APP_GLuint index);
  void(APP_GLCALLTYPE *VertexAttribPointer)(APP_GLuint index, APP_GLint size,
                                            APP_GLenum type,
                                            APP_GLboolean normalized,
                                            APP_GLsizei stride,
                                            void const *pointer);
  void(APP_GLCALLTYPE *GenTextures)(APP_GLsizei n, APP_GLuint *textures);
  void(APP_GLCALLTYPE *Enable)(APP_GLenum cap);
  void(APP_GLCALLTYPE *ActiveTexture)(APP_GLenum texture);
  void(APP_GLCALLTYPE *BindTexture)(APP_GLenum target, APP_GLuint texture);
  void(APP_GLCALLTYPE *TexParameteri)(APP_GLenum target, APP_GLenum pname,
                                      APP_GLint param);
  void(APP_GLCALLTYPE *DeleteBuffers)(APP_GLsizei n, APP_GLuint const *buffers);
  void(APP_GLCALLTYPE *DeleteTextures)(APP_GLsizei n,
                                       APP_GLuint const *textures);
  void(APP_GLCALLTYPE *BufferData)(APP_GLenum target, APP_GLsizeiptr size,
                                   void const *data, APP_GLenum usage);
  void(APP_GLCALLTYPE *UseProgram)(APP_GLuint program);
  void(APP_GLCALLTYPE *Uniform1i)(APP_GLint location, APP_GLint v0);
  void(APP_GLCALLTYPE *Uniform3f)(APP_GLint location, APP_GLfloat v0,
                                  APP_GLfloat v1, APP_GLfloat v2);
  APP_GLint(APP_GLCALLTYPE *GetUniformLocation)(APP_GLuint program,
                                                APP_GLchar const *name);
  void(APP_GLCALLTYPE *TexImage2D)(APP_GLenum target, APP_GLint level,
                                   APP_GLint internalformat, APP_GLsizei width,
                                   APP_GLsizei height, APP_GLint border,
                                   APP_GLenum format, APP_GLenum type,
                                   void const *pixels);
  void(APP_GLCALLTYPE *ClearColor)(APP_GLfloat red, APP_GLfloat green,
                                   APP_GLfloat blue, APP_GLfloat alpha);
  void(APP_GLCALLTYPE *Clear)(APP_GLbitfield mask);
  void(APP_GLCALLTYPE *DrawArrays)(APP_GLenum mode, APP_GLint first,
                                   APP_GLsizei count);
  void(APP_GLCALLTYPE *Viewport)(APP_GLint x, APP_GLint y, APP_GLsizei width,
                                 APP_GLsizei height);
  void(APP_GLCALLTYPE *DeleteShader)(APP_GLuint shader);
  void(APP_GLCALLTYPE *DeleteProgram)(APP_GLuint program);
#ifdef APP_REPORT_SHADER_ERRORS
  void(APP_GLCALLTYPE *GetShaderInfoLog)(APP_GLuint shader, APP_GLsizei bufSize,
                                         APP_GLsizei *length,
                                         APP_GLchar *infoLog);
#endif

  app_interpolation_t interpolation;
  int window_width;
  int window_height;

  APP_GLuint vertexbuffer;
  APP_GLuint texture;
  APP_GLuint shader;
};
#endif