/*
 * Copyright (C) 2011 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.
 */
// #define LOG_NDEBUG 0

#include "base/logging.h"
#include "base/utilities.h"
#include "core/gl_env.h"
#include "core/shader_program.h"
#include "core/vertex_frame.h"
#include "system/window.h"

#include <map>
#include <string>
#include <EGL/eglext.h>

namespace android {
namespace filterfw {

GLEnv::GLEnv()
  : display_(EGL_NO_DISPLAY),
    context_id_(0),
    surface_id_(0),
    max_surface_id_(0),
    created_context_(false),
    created_surface_(false),
    initialized_(false) {
}

GLEnv::~GLEnv() {
  // Destroy surfaces
  for (std::map<int, SurfaceWindowPair>::iterator it = surfaces_.begin();
       it != surfaces_.end();
       ++it) {
    if (it->first != 0 || created_surface_) {
      eglDestroySurface(display(), it->second.first);
      if (it->second.second) {
        it->second.second->Destroy();
        delete it->second.second;
      }
    }
  }

  // Destroy contexts
  for (std::map<int, EGLContext>::iterator it = contexts_.begin();
       it != contexts_.end();
       ++it) {
    if (it->first != 0 || created_context_)
      eglDestroyContext(display(), it->second);
  }

  // Destroy attached shaders and frames
  STLDeleteValues(&attached_shaders_);
  STLDeleteValues(&attached_vframes_);

  // Destroy display
  if (initialized_)
    eglTerminate(display());

  // Log error if this did not work
  if (CheckEGLError("TearDown!"))
    ALOGE("GLEnv: Error tearing down GL Environment!");
}

bool GLEnv::IsInitialized() const {
  return (contexts_.size() > 0 &&
          surfaces_.size() > 0 &&
          display_ != EGL_NO_DISPLAY);
}

bool GLEnv::Deactivate() {
  eglMakeCurrent(display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
  return !CheckEGLError("eglMakeCurrent");
}

bool GLEnv::Activate() {
  ALOGV("Activate()");
  if (display()   != eglGetCurrentDisplay() ||
      context()   != eglGetCurrentContext() ||
      surface()   != eglGetCurrentSurface(EGL_DRAW)) {
    // Make sure we are initialized
    if (context() == EGL_NO_CONTEXT || surface() == EGL_NO_SURFACE)
      return false;

    // Make our context current
    ALOGV("eglMakeCurrent");
    eglMakeCurrent(display(), surface(), surface(), context());

    return !CheckEGLMakeCurrentError();
  }
  return true;
}

bool GLEnv::SwapBuffers() {
  const bool result = eglSwapBuffers(display(), surface()) == EGL_TRUE;
  return !CheckEGLError("eglSwapBuffers") && result;
}

bool GLEnv::InitWithCurrentContext() {
  if (IsInitialized())
    return true;

  display_     = eglGetCurrentDisplay();
  contexts_[0] = eglGetCurrentContext();
  surfaces_[0] = SurfaceWindowPair(eglGetCurrentSurface(EGL_DRAW), NULL);

  return (context() != EGL_NO_CONTEXT) &&
         (display() != EGL_NO_DISPLAY) &&
         (surface() != EGL_NO_SURFACE);
}

bool GLEnv::InitWithNewContext() {
  if (IsInitialized()) {
    ALOGE("GLEnv: Attempting to reinitialize environment!");
    return false;
  }

  display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  if (CheckEGLError("eglGetDisplay")) return false;

  EGLint majorVersion;
  EGLint minorVersion;
  eglInitialize(display(), &majorVersion, &minorVersion);
  if (CheckEGLError("eglInitialize")) return false;
  initialized_ = true;

  // Configure context/surface
  EGLConfig config;
  EGLint numConfigs = -1;

  // TODO(renn): Do we need the window bit here?
  // TODO: Currently choosing the config that includes all
  // This is not needed if the encoding is not being used
  EGLint configAttribs[] = {
    EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
    EGL_RED_SIZE, 8,
    EGL_GREEN_SIZE, 8,
    EGL_BLUE_SIZE, 8,
    EGL_RECORDABLE_ANDROID, EGL_TRUE,
    EGL_NONE
  };

  eglChooseConfig(display(), configAttribs, &config, 1, &numConfigs);
  if (numConfigs < 1) {
    ALOGE("GLEnv::Init: No suitable EGL configuration found!");
    return false;
  }

  // Create dummy surface using a GLConsumer
  sp<BufferQueue> bq = new BufferQueue();
  surfaceTexture_ = new GLConsumer(bq, 0);
  window_ = new Surface(static_cast<sp<IGraphicBufferProducer> >(
          surfaceTexture_->getBufferQueue()));

  surfaces_[0] = SurfaceWindowPair(eglCreateWindowSurface(display(), config, window_.get(), NULL), NULL);
  if (CheckEGLError("eglCreateWindowSurface")) return false;

  // Create context
  EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
  contexts_[0] = eglCreateContext(display(),
                                  config,
                                  EGL_NO_CONTEXT,
                                  context_attribs);
  if (CheckEGLError("eglCreateContext")) return false;

  created_context_ = created_surface_ = true;

  return true;
}

bool GLEnv::IsActive() const {
  ALOGV("IsActive()");
  return context() == eglGetCurrentContext()
    &&   display() == eglGetCurrentDisplay()
    &&   surface() == eglGetCurrentSurface(EGL_DRAW);
}

bool GLEnv::IsContextActive() const {
  return context() == eglGetCurrentContext();
}

bool GLEnv::IsAnyContextActive() {
  return eglGetCurrentContext() != EGL_NO_CONTEXT;
}

int GLEnv::AddWindowSurface(const EGLSurface& surface, WindowHandle* window_handle) {
  const int id = ++max_surface_id_;
  surfaces_[id] = SurfaceWindowPair(surface, window_handle);
  return id;
}

int GLEnv::AddSurface(const EGLSurface& surface) {
  return AddWindowSurface(surface, NULL);
}

bool GLEnv::SwitchToSurfaceId(int surface_id) {
  ALOGV("SwitchToSurfaceId");
  if (surface_id_ != surface_id) {
    const SurfaceWindowPair* surface = FindOrNull(surfaces_, surface_id);
    if (surface) {
      bool wasActive = IsActive();
      surface_id_ = surface_id;
      return wasActive ? Activate() : true;
    }
    return false;
  }
  return true;
}

bool GLEnv::ReleaseSurfaceId(int surface_id) {
  if (surface_id > 0) {
    const SurfaceWindowPair* surface_window_pair = FindOrNull(surfaces_, surface_id);
    if (surface_window_pair) {
      if (surface_id_ == surface_id)
        SwitchToSurfaceId(0);
      eglDestroySurface(display(), surface_window_pair->first);
      if (surface_window_pair->second) {
        surface_window_pair->second->Destroy();
        delete surface_window_pair->second;
      }
      surfaces_.erase(surface_id);
      return true;
    }
  }
  return false;
}

bool GLEnv::SetSurfaceTimestamp(int64_t timestamp) {
  if (surface_id_ > 0) {
    const SurfaceWindowPair* surface_window_pair = FindOrNull(surfaces_,
            surface_id_);
    if (surface_window_pair) {
      ANativeWindow *window = static_cast<ANativeWindow*>(
              surface_window_pair->second->InternalHandle());
      native_window_set_buffers_timestamp(window, timestamp);
      return true;
    }
  }
  return false;
}

int GLEnv::FindSurfaceIdForWindow(const WindowHandle* window_handle) {
  for (std::map<int, SurfaceWindowPair>::iterator it = surfaces_.begin();
       it != surfaces_.end();
       ++it) {
    const WindowHandle* my_handle = it->second.second;
    if (my_handle && my_handle->Equals(window_handle)) {
      return it->first;
    }
  }
  return -1;
}


int GLEnv::AddContext(const EGLContext& context) {
  const int id = contexts_.size();
  contexts_[id] = context;
  return id;
}

bool GLEnv::SwitchToContextId(int context_id) {
  const EGLContext* context = FindOrNull(contexts_, context_id);
  if (context) {
    if (context_id_ != context_id) {
      context_id_ = context_id;
      return Activate();
    }
    return true;
  }
  return false;
}

void GLEnv::ReleaseContextId(int context_id) {
  if (context_id > 0) {
    const EGLContext* context = FindOrNull(contexts_, context_id);
    if (context) {
      contexts_.erase(context_id);
      if (context_id_ == context_id && IsActive())
        SwitchToContextId(0);
      eglDestroyContext(display(), *context);
    }
  }
}

bool GLEnv::CheckGLError(const std::string& op) {
  bool err = false;
  for (GLint error = glGetError(); error; error = glGetError()) {
    ALOGE("GL Error: Operation '%s' caused GL error (0x%x)\n",
         op.c_str(),
         error);
    err = true;
  }
  return err;
}

bool GLEnv::CheckEGLError(const std::string& op) {
  bool err = false;
  for (EGLint error = eglGetError();
       error != EGL_SUCCESS;
       error = eglGetError()) {
    ALOGE("EGL Error: Operation '%s' caused EGL error (0x%x)\n",
         op.c_str(),
         error);
    err = true;
  }
  return err;
}

bool GLEnv::CheckEGLMakeCurrentError() {
  bool err = false;
  for (EGLint error = eglGetError();
       error != EGL_SUCCESS;
       error = eglGetError()) {
    switch (error) {
      case EGL_BAD_DISPLAY:
        ALOGE("EGL Error: Attempting to activate context with bad display!");
        break;
      case EGL_BAD_SURFACE:
        ALOGE("EGL Error: Attempting to activate context with bad surface!");
        break;
      case EGL_BAD_ACCESS:
        ALOGE("EGL Error: Attempting to activate context, which is "
             "already active in another thread!");
        break;
      default:
        ALOGE("EGL Error: Making EGL rendering context current caused "
             "error: 0x%x\n", error);
    }
    err = true;
  }
  return err;
}

GLuint GLEnv::GetCurrentProgram() {
  GLint result;
  glGetIntegerv(GL_CURRENT_PROGRAM, &result);
  ALOG_ASSERT(result >= 0);
  return static_cast<GLuint>(result);
}

EGLDisplay GLEnv::GetCurrentDisplay() {
  return eglGetCurrentDisplay();
}

int GLEnv::NumberOfComponents(GLenum type) {
  switch (type) {
    case GL_BOOL:
    case GL_FLOAT:
    case GL_INT:
      return 1;
    case GL_BOOL_VEC2:
    case GL_FLOAT_VEC2:
    case GL_INT_VEC2:
      return 2;
    case GL_INT_VEC3:
    case GL_FLOAT_VEC3:
    case GL_BOOL_VEC3:
      return 3;
    case GL_BOOL_VEC4:
    case GL_FLOAT_VEC4:
    case GL_INT_VEC4:
    case GL_FLOAT_MAT2:
      return 4;
    case GL_FLOAT_MAT3:
      return 9;
    case GL_FLOAT_MAT4:
      return 16;
    default:
      return 0;
  }
}

void GLEnv::AttachShader(int key, ShaderProgram* shader) {
  ShaderProgram* existingShader = ShaderWithKey(key);
  if (existingShader)
    delete existingShader;
  attached_shaders_[key] = shader;
}

void GLEnv::AttachVertexFrame(int key, VertexFrame* frame) {
  VertexFrame* existingFrame = VertexFrameWithKey(key);
  if (existingFrame)
    delete existingFrame;
  attached_vframes_[key] = frame;
}

ShaderProgram* GLEnv::ShaderWithKey(int key) {
  return FindPtrOrNull(attached_shaders_, key);
}

VertexFrame* GLEnv::VertexFrameWithKey(int key) {
  return FindPtrOrNull(attached_vframes_, key);
}

} // namespace filterfw
} // namespace android
