/*
 * Copyright 2015 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 "glimp/egl/display.h"

#include <algorithm>
#include <utility>
#include <vector>

#include "glimp/egl/config.h"
#include "glimp/egl/error.h"
#include "starboard/common/log.h"
#include "starboard/event.h"

namespace glimp {
namespace egl {

const int64_t kSubmitDoneDelay = 1000000 / 60;  // 1/60 seconds, in microseconds

// Don't repeat the submitDone callback during suspension
// until specified by eglTerminate.
bool Display::repeat_submit_done_during_suspend = false;

namespace {
void ScheduleSubmitDoneCallback(void* context) {
  if (Display::repeat_submit_done_during_suspend) {
    SB_DCHECK(true) << "Suspend mode is disabled. ScheduleSubmitDoneCallback "
                       "shouldn't be triggered.";
    DisplayImpl::CallSubmitDone();
    Display::RepeatSubmitDoneDuringSuspend();
  }
}
}  // namespace

void Display::RepeatSubmitDoneDuringSuspend() {
  static SbEventId submit_done_repeating_callback_event = kSbEventIdInvalid;
  if (Display::repeat_submit_done_during_suspend) {
    submit_done_repeating_callback_event =
        SbEventSchedule(&ScheduleSubmitDoneCallback, NULL, kSubmitDoneDelay);
  } else {
    if (submit_done_repeating_callback_event != kSbEventIdInvalid) {
      SbEventCancel(submit_done_repeating_callback_event);
    }
  }
}

Display::Display(std::unique_ptr<DisplayImpl> display_impl)
    : impl_(std::move(display_impl)) {}

Display::~Display() {
  SB_DCHECK(active_surfaces_.empty());
}

void Display::GetVersionInfo(EGLint* major, EGLint* minor) {
  DisplayImpl::VersionInfo version_info = impl_->GetVersionInfo();
  if (major) {
    *major = version_info.major;
  }
  if (minor) {
    *minor = version_info.minor;
  }
}

bool Display::ChooseConfig(const EGLint* attrib_list,
                           EGLConfig* configs,
                           EGLint config_size,
                           EGLint* num_config) {
  if (!num_config) {
    SetError(EGL_BAD_PARAMETER);
    return false;
  }
  AttribMap attribs = ParseRawAttribList(attrib_list);
  if (!ValidateConfigAttribList(attribs)) {
    SetError(EGL_BAD_ATTRIBUTE);
    return false;
  }

  std::vector<Config*> configs_vector =
      FilterConfigs(impl_->GetSupportedConfigs(), attribs);
  SortConfigs(attribs, &configs_vector);

  if (configs) {
    *num_config =
        std::min(config_size, static_cast<int>(configs_vector.size()));
    for (int i = 0; i < *num_config; ++i) {
      configs[i] = ToEGLConfig(configs_vector[i]);
    }
  } else {
    *num_config = static_cast<int>(configs_vector.size());
  }

  return true;
}

bool Display::ConfigIsValid(EGLConfig config) {
  const DisplayImpl::ConfigSet& supported_configs =
      impl_->GetSupportedConfigs();

  return supported_configs.find(reinterpret_cast<Config*>(config)) !=
         supported_configs.end();
}

EGLSurface Display::CreateWindowSurface(EGLConfig config,
                                        EGLNativeWindowType win,
                                        const EGLint* attrib_list) {
  AttribMap attribs = ParseRawAttribList(attrib_list);
  if (!ValidateSurfaceAttribList(attribs)) {
    SetError(EGL_BAD_ATTRIBUTE);
    return EGL_NO_SURFACE;
  }

  if (!ConfigIsValid(config)) {
    SetError(EGL_BAD_CONFIG);
    return EGL_NO_SURFACE;
  }

  if (!((*reinterpret_cast<Config*>(config))[EGL_SURFACE_TYPE] |
        EGL_WINDOW_BIT)) {
    // The config used must have the EGL_WINDOW_BIT set in order for us to
    // be able to create windows.
    SetError(EGL_BAD_MATCH);
    return EGL_NO_SURFACE;
  }

  std::unique_ptr<SurfaceImpl> surface_impl = impl_->CreateWindowSurface(
      reinterpret_cast<Config*>(config), win, attribs);
  if (!surface_impl) {
    return EGL_NO_SURFACE;
  }

  Surface* surface = new Surface(std::move(surface_impl));
  active_surfaces_.insert(surface);

  return ToEGLSurface(surface);
}

EGLSurface Display::CreatePbufferSurface(EGLConfig config,
                                         const EGLint* attrib_list) {
  AttribMap attribs = ParseRawAttribList(attrib_list);
  if (!ValidateSurfaceAttribList(attribs)) {
    SetError(EGL_BAD_ATTRIBUTE);
    return EGL_NO_SURFACE;
  }

  if (!ConfigIsValid(config)) {
    SetError(EGL_BAD_CONFIG);
    return EGL_NO_SURFACE;
  }

  if (!((*reinterpret_cast<Config*>(config))[EGL_SURFACE_TYPE] |
        EGL_PBUFFER_BIT)) {
    // The config used must have the EGL_PBUFFER_BIT set in order for us to
    // be able to create pbuffers.
    SetError(EGL_BAD_MATCH);
    return EGL_NO_SURFACE;
  }

  std::unique_ptr<SurfaceImpl> surface_impl =
      impl_->CreatePbufferSurface(reinterpret_cast<Config*>(config), attribs);
  if (!surface_impl) {
    return EGL_NO_SURFACE;
  }

  Surface* surface = new Surface(std::move(surface_impl));
  active_surfaces_.insert(surface);

  return ToEGLSurface(surface);
}

bool Display::SurfaceIsValid(EGLSurface surface) {
  return active_surfaces_.find(FromEGLSurface(surface)) !=
         active_surfaces_.end();
}

bool Display::DestroySurface(EGLSurface surface) {
  if (!SurfaceIsValid(surface)) {
    SetError(EGL_BAD_SURFACE);
    return false;
  }

  Surface* surf = FromEGLSurface(surface);
  active_surfaces_.erase(surf);
  delete surf;
  return true;
}

namespace {
// Returns -1 if the context attributes are invalid.
int GetContextVersion(const EGLint* attrib_list) {
  AttribMap attribs = ParseRawAttribList(attrib_list);

  // According to
  //   https://www.khronos.org/registry/egl/sdk/docs/man/html/eglCreateContext.xhtml,
  // the default version of the GL ES context is 1.
  if (attribs.empty()) {
    return 1;
  }

  // EGL_CONTEXT_CLIENT_VERSION is the only valid attribute for CreateContext.
  AttribMap::const_iterator found = attribs.find(EGL_CONTEXT_CLIENT_VERSION);
  if (found == attribs.end()) {
    // If we didn't find it, and the attribute list is not empty (checked above)
    // then this is an invalid attribute list.
    return -1;
  } else {
    return found->second;
  }
}
}  // namespace

EGLContext Display::CreateContext(EGLConfig config,
                                  EGLContext share_context,
                                  const EGLint* attrib_list) {
  // glimp only supports GL ES versions 2 and 3.
  int context_version = GetContextVersion(attrib_list);
  if (context_version != 2 && context_version != 3) {
    SetError(EGL_BAD_ATTRIBUTE);
    return EGL_NO_CONTEXT;
  }

  if (!ConfigIsValid(config)) {
    SetError(EGL_BAD_CONFIG);
    return EGL_NO_CONTEXT;
  }

  // Ensure that |share_context| is either unspecified, or valid.
  gles::Context* share = NULL;
  if (share_context != EGL_NO_CONTEXT) {
    if (!ContextIsValid(share_context)) {
      SetError(EGL_BAD_CONTEXT);
      return EGL_NO_CONTEXT;
    }
    share = reinterpret_cast<gles::Context*>(share_context);
  }

  std::unique_ptr<gles::ContextImpl> context_impl =
      impl_->CreateContext(reinterpret_cast<Config*>(config), context_version);
  if (!context_impl) {
    return EGL_NO_CONTEXT;
  }

  gles::Context* context = new gles::Context(std::move(context_impl), share);
  active_contexts_.insert(context);

  return reinterpret_cast<EGLContext>(context);
}

bool Display::ContextIsValid(EGLContext context) {
  return active_contexts_.find(reinterpret_cast<gles::Context*>(context)) !=
         active_contexts_.end();
}

bool Display::DestroyContext(EGLContext ctx) {
  if (!ContextIsValid(ctx)) {
    SetError(EGL_BAD_CONTEXT);
    return false;
  }

  gles::Context* context = reinterpret_cast<gles::Context*>(ctx);
  active_contexts_.erase(context);
  delete context;
  return true;
}

bool Display::MakeCurrent(EGLSurface draw, EGLSurface read, EGLContext ctx) {
  if (draw == EGL_NO_SURFACE && read == EGL_NO_SURFACE &&
      ctx == EGL_NO_CONTEXT) {
    if (!ContextIsValid(reinterpret_cast<EGLContext>(
            gles::Context::GetTLSCurrentContext()))) {
      SB_DLOG(WARNING)
          << "Attempted to release a context not owned by this display.";
      SetError(EGL_BAD_CONTEXT);
      return false;
    }
    gles::Context::ReleaseTLSCurrentContext();
    return true;
  }

  if (!ContextIsValid(ctx)) {
    SetError(EGL_BAD_CONTEXT);
    return false;
  }

  if (!SurfaceIsValid(draw)) {
    SetError(EGL_BAD_SURFACE);
    return false;
  }

  if (!SurfaceIsValid(read)) {
    SetError(EGL_BAD_SURFACE);
    return false;
  }

  return gles::Context::SetTLSCurrentContext(
      reinterpret_cast<gles::Context*>(ctx), FromEGLSurface(draw),
      FromEGLSurface(read));
}

bool Display::SwapBuffers(EGLSurface surface) {
  if (!SurfaceIsValid(surface)) {
    SetError(EGL_BAD_SURFACE);
    return false;
  }
  Surface* surface_object = FromEGLSurface(surface);

  gles::Context* current_context = gles::Context::GetTLSCurrentContext();
  if (!ContextIsValid(reinterpret_cast<EGLContext>(current_context))) {
    // The specification for eglSwapBuffers() does not explicitly state that
    // the surface's context needs to be current when eglSwapBuffers() is
    // called, but we enforce this in glimp as it is a very typical use-case and
    // it considerably simplifies the process.
    SB_DLOG(WARNING)
        << "eglSwapBuffers() called when no or an invalid context was current.";
    SetError(EGL_BAD_SURFACE);
    return false;
  }

  if (current_context->draw_surface() != surface_object) {
    SB_DLOG(WARNING)
        << "eglSwapBuffers() called on a surface that is not the draw surface "
        << "of the current context.";
    SetError(EGL_BAD_SURFACE);
    return false;
  }

  current_context->SwapBuffers();
  return true;
}

bool Display::SwapInterval(EGLint interval) {
  return impl_->SetSwapInterval(interval);
}

}  // namespace egl
}  // namespace glimp
