// Copyright 2016 The Cobalt Authors. All Rights Reserved.
//
// 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 <EGL/egl.h>
#include <GLES2/gl2.h>
#include <math.h>

#include <iomanip>

#include "starboard/event.h"
#include "starboard/input.h"
#include "starboard/log.h"
#include "starboard/memory.h"
#include "starboard/system.h"
#include "starboard/window.h"

namespace {

EGLint const kAttributeList[] = {EGL_RED_SIZE,
                                 8,
                                 EGL_GREEN_SIZE,
                                 8,
                                 EGL_BLUE_SIZE,
                                 8,
                                 EGL_ALPHA_SIZE,
                                 8,
                                 EGL_STENCIL_SIZE,
                                 0,
                                 EGL_BUFFER_SIZE,
                                 32,
                                 EGL_SURFACE_TYPE,
                                 EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
                                 EGL_COLOR_BUFFER_TYPE,
                                 EGL_RGB_BUFFER,
                                 EGL_CONFORMANT,
                                 EGL_OPENGL_ES2_BIT,
                                 EGL_RENDERABLE_TYPE,
                                 EGL_OPENGL_ES2_BIT,
                                 EGL_NONE};
}  // namespace

class Application {
 public:
  Application();
  ~Application();

 private:
  // The callback function passed to SbEventSchedule().  Its purpose is to
  // forward to the non-static RenderScene() method.
  static void RenderSceneEventCallback(void* param);

  // Renders one frame of the animated scene, incrementing |frame_| each time
  // it is called.
  void RenderScene();

  // The current frame we are rendering, initialized to 0 and incremented after
  // each frame.
  int frame_;

  // The SbWindow within which we will perform our rendering.
  SbWindow window_;

  EGLDisplay display_;
  EGLSurface surface_;
  EGLContext context_;

  EGLint egl_surface_width_;
  EGLint egl_surface_height_;
};

Application::Application() {
  frame_ = 0;

  SbWindowOptions options;
  SbWindowSetDefaultOptions(&options);
  window_ = SbWindowCreate(&options);
  SB_CHECK(SbWindowIsValid(window_));

  display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  SB_CHECK(EGL_SUCCESS == eglGetError());
  SB_CHECK(EGL_NO_DISPLAY != display_);

  eglInitialize(display_, NULL, NULL);
  SB_CHECK(EGL_SUCCESS == eglGetError());

  // Some EGL drivers can return a first config that doesn't allow
  // eglCreateWindowSurface(), with no differences in EGLConfig attribute values
  // from configs that do allow that. To handle that, we have to attempt
  // eglCreateWindowSurface() until we find a config that succeeds.

  // First, query how many configs match the given attribute list.
  EGLint num_configs = 0;
  eglChooseConfig(display_, kAttributeList, NULL, 0, &num_configs);
  SB_CHECK(EGL_SUCCESS == eglGetError());
  SB_CHECK(0 != num_configs);

  // Allocate space to receive the matching configs and retrieve them.
  EGLConfig* configs = reinterpret_cast<EGLConfig*>(
      SbMemoryAllocate(num_configs * sizeof(EGLConfig)));
  eglChooseConfig(display_, kAttributeList, configs, num_configs, &num_configs);
  SB_CHECK(EGL_SUCCESS == eglGetError());

  EGLNativeWindowType native_window =
      (EGLNativeWindowType)SbWindowGetPlatformHandle(window_);
  EGLConfig config;

  // Find the first config that successfully allow a window surface to be
  // created.
  for (int config_number = 0; config_number < num_configs; ++config_number) {
    config = configs[config_number];
    surface_ = eglCreateWindowSurface(display_, config, native_window, NULL);
    if (EGL_SUCCESS == eglGetError())
      break;
  }
  SB_DCHECK(surface_ != EGL_NO_SURFACE);

  SbMemoryDeallocate(configs);

  eglQuerySurface(display_, surface_, EGL_WIDTH, &egl_surface_width_);
  eglQuerySurface(display_, surface_, EGL_HEIGHT, &egl_surface_height_);
  SB_DCHECK(egl_surface_width_ > 0);
  SB_DCHECK(egl_surface_height_ > 0);

  // Create the GLES2 or GLEX3 Context.
  context_ = EGL_NO_CONTEXT;
  EGLint context_attrib_list[] = {
      EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE,
  };
#if defined(GLES3_SUPPORTED)
  // Attempt to create an OpenGL ES 3.0 context.
  context_ =
      eglCreateContext(display_, config, EGL_NO_CONTEXT, context_attrib_list);
#endif
  if (context_ == EGL_NO_CONTEXT) {
    // Create an OpenGL ES 2.0 context.
    context_attrib_list[1] = 2;
    context_ =
        eglCreateContext(display_, config, EGL_NO_CONTEXT, context_attrib_list);
  }
  SB_CHECK(EGL_SUCCESS == eglGetError());
  SB_CHECK(context_ != EGL_NO_CONTEXT);

  /* connect the context to the surface */
  eglMakeCurrent(display_, surface_, surface_, context_);
  SB_CHECK(EGL_SUCCESS == eglGetError());

  RenderScene();
}

Application::~Application() {
  // Cleanup all used resources.
  eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
  SB_CHECK(EGL_SUCCESS == eglGetError());
  eglDestroyContext(display_, context_);
  SB_CHECK(EGL_SUCCESS == eglGetError());
  eglDestroySurface(display_, surface_);
  SB_CHECK(EGL_SUCCESS == eglGetError());
  eglTerminate(display_);
  SB_CHECK(EGL_SUCCESS == eglGetError());
  SbWindowDestroy(window_);
}

void Application::RenderSceneEventCallback(void* param) {
  // Forward the call to the application instance specified as the parameter.
  Application* application = static_cast<Application*>(param);
  application->RenderScene();
}

namespace {

float getIntensity(int frame, float rate) {
  float radian = 2 * M_PI * frame / rate;
  return 0.5 + 0.5 * sin(radian);
}

}  // namespace

void Application::RenderScene() {
  // Render a moving and color changing rectangle using glClear() and
  // glScissor().
  glEnable(GL_SCISSOR_TEST);

  float radian = 2 * M_PI * frame_ / 600.0f;
  int offset_x = egl_surface_height_ * sin(radian) / 3.6;
  int offset_y = egl_surface_height_ * cos(radian) / 3.6;

  int block_width = egl_surface_width_ / 16;
  int block_height = egl_surface_height_ / 9;

  int center_x = (egl_surface_width_ - block_width) / 2;
  int center_y = (egl_surface_height_ - block_height) / 2;

  glScissor(center_x + offset_x, center_y + offset_y, block_width,
            block_height);
  SB_CHECK(GL_NO_ERROR == glGetError());

  glClearColor(getIntensity(frame_, 55.0f), getIntensity(frame_, 60.0f),
               getIntensity(frame_, 62.5f), 1.0);
  SB_CHECK(GL_NO_ERROR == glGetError());

  glClear(GL_COLOR_BUFFER_BIT);
  SB_CHECK(GL_NO_ERROR == glGetError());

  glFlush();
  SB_CHECK(GL_NO_ERROR == glGetError());

  eglSwapBuffers(display_, surface_);
  SB_CHECK(EGL_SUCCESS == eglGetError());

  // Schedule another frame render ASAP.
  SbEventSchedule(&Application::RenderSceneEventCallback, this, 0);
  ++frame_;
}

Application* s_application = NULL;

// Simple Starboard window event handling to kick off our color animating
// application.
void SbEventHandle(const SbEvent* event) {
  switch (event->type) {
    case kSbEventTypeStart: {
      // Create the application, after which it will use SbEventSchedule()
      // on itself to trigger a frame update until the application is
      // terminated.
      s_application = new Application();
    } break;

    case kSbEventTypeStop: {
      // Shutdown the application.
      delete s_application;
    } break;

    default: {}
  }
}
