/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif

#include "webrtc/modules/video_render/ios/video_render_ios_gles20.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h"

using namespace webrtc;

VideoRenderIosGles20::VideoRenderIosGles20(VideoRenderIosView* view,
                                           bool full_screen,
                                           int render_id)
    : gles_crit_sec_(CriticalSectionWrapper::CreateCriticalSection()),
      screen_update_event_(0),
      view_(view),
      window_rect_(),
      window_width_(0),
      window_height_(0),
      is_full_screen_(full_screen),
      agl_channels_(),
      z_order_to_channel_(),
      gles_context_([view context]),
      is_rendering_(true) {
  screen_update_thread_ = ThreadWrapper::CreateThread(
      ScreenUpdateThreadProc, this, "ScreenUpdateGles20");
  screen_update_event_ = EventTimerWrapper::Create();
  GetWindowRect(window_rect_);
}

VideoRenderIosGles20::~VideoRenderIosGles20() {
  // Signal event to exit thread, then delete it
  ThreadWrapper* thread_wrapper = screen_update_thread_.release();

  if (thread_wrapper) {
    screen_update_event_->Set();
    screen_update_event_->StopTimer();

    thread_wrapper->Stop();
    delete thread_wrapper;
    delete screen_update_event_;
    screen_update_event_ = NULL;
    is_rendering_ = FALSE;
  }

  // Delete all channels
  std::map<int, VideoRenderIosChannel*>::iterator it = agl_channels_.begin();
  while (it != agl_channels_.end()) {
    delete it->second;
    agl_channels_.erase(it);
    it = agl_channels_.begin();
  }
  agl_channels_.clear();

  // Clean the zOrder map
  std::multimap<int, int>::iterator z_it = z_order_to_channel_.begin();
  while (z_it != z_order_to_channel_.end()) {
    z_order_to_channel_.erase(z_it);
    z_it = z_order_to_channel_.begin();
  }
  z_order_to_channel_.clear();
}

int VideoRenderIosGles20::Init() {
  CriticalSectionScoped cs(gles_crit_sec_.get());

  if (!view_) {
    view_ = [[VideoRenderIosView alloc] init];
  }

  if (![view_ createContext]) {
    return -1;
  }

  screen_update_thread_->Start();
  screen_update_thread_->SetPriority(kRealtimePriority);

  // Start the event triggering the render process
  unsigned int monitor_freq = 60;
  screen_update_event_->StartTimer(true, 1000 / monitor_freq);

  window_width_ = window_rect_.right - window_rect_.left;
  window_height_ = window_rect_.bottom - window_rect_.top;

  return 0;
}

VideoRenderIosChannel* VideoRenderIosGles20::CreateEaglChannel(int channel,
                                                               int z_order,
                                                               float left,
                                                               float top,
                                                               float right,
                                                               float bottom) {
  CriticalSectionScoped cs(gles_crit_sec_.get());

  if (HasChannel(channel)) {
    return NULL;
  }

  VideoRenderIosChannel* new_eagl_channel = new VideoRenderIosChannel(view_);

  if (new_eagl_channel->SetStreamSettings(z_order, left, top, right, bottom) ==
      -1) {
    return NULL;
  }

  agl_channels_[channel] = new_eagl_channel;
  z_order_to_channel_.insert(std::pair<int, int>(z_order, channel));

  return new_eagl_channel;
}

int VideoRenderIosGles20::DeleteEaglChannel(int channel) {
  CriticalSectionScoped cs(gles_crit_sec_.get());

  std::map<int, VideoRenderIosChannel*>::iterator it;
  it = agl_channels_.find(channel);
  if (it != agl_channels_.end()) {
    delete it->second;
    agl_channels_.erase(it);
  } else {
    return -1;
  }

  std::multimap<int, int>::iterator z_it = z_order_to_channel_.begin();
  while (z_it != z_order_to_channel_.end()) {
    if (z_it->second == channel) {
      z_order_to_channel_.erase(z_it);
      break;
    }
    z_it++;
  }

  return 0;
}

bool VideoRenderIosGles20::HasChannel(int channel) {
  CriticalSectionScoped cs(gles_crit_sec_.get());

  std::map<int, VideoRenderIosChannel*>::iterator it =
      agl_channels_.find(channel);

  if (it != agl_channels_.end()) {
    return true;
  }

  return false;
}

// Rendering process
bool VideoRenderIosGles20::ScreenUpdateThreadProc(void* obj) {
  return static_cast<VideoRenderIosGles20*>(obj)->ScreenUpdateProcess();
}

bool VideoRenderIosGles20::ScreenUpdateProcess() {
  screen_update_event_->Wait(100);

  CriticalSectionScoped cs(gles_crit_sec_.get());

  if (!is_rendering_) {
    return false;
  }

  if (!screen_update_thread_) {
    return false;
  }

  if (GetWindowRect(window_rect_) == -1) {
    return true;
  }

  if (window_width_ != (window_rect_.right - window_rect_.left) ||
      window_height_ != (window_rect_.bottom - window_rect_.top)) {
    window_width_ = window_rect_.right - window_rect_.left;
    window_height_ = window_rect_.bottom - window_rect_.top;
  }

  // Check if there are any updated buffers
  bool updated = false;

  std::map<int, VideoRenderIosChannel*>::iterator it = agl_channels_.begin();
  while (it != agl_channels_.end()) {
    VideoRenderIosChannel* agl_channel = it->second;

    updated = agl_channel->IsUpdated();
    if (updated) {
      break;
    }
    it++;
  }

  if (updated) {
    // At least one buffer has been updated, we need to repaint the texture
    // Loop through all channels starting highest zOrder ending with lowest.
    for (std::multimap<int, int>::reverse_iterator r_it =
             z_order_to_channel_.rbegin();
         r_it != z_order_to_channel_.rend();
         r_it++) {
      int channel_id = r_it->second;
      std::map<int, VideoRenderIosChannel*>::iterator it =
          agl_channels_.find(channel_id);

      VideoRenderIosChannel* agl_channel = it->second;

      agl_channel->RenderOffScreenBuffer();
    }

    [view_ presentFramebuffer];
  }

  return true;
}

int VideoRenderIosGles20::GetWindowRect(Rect& rect) {
  CriticalSectionScoped cs(gles_crit_sec_.get());

  if (!view_) {
    return -1;
  }

  CGRect bounds = [view_ bounds];
  rect.top = bounds.origin.y;
  rect.left = bounds.origin.x;
  rect.bottom = bounds.size.height + bounds.origin.y;
  rect.right = bounds.size.width + bounds.origin.x;

  return 0;
}

int VideoRenderIosGles20::ChangeWindow(void* new_window) {
  CriticalSectionScoped cs(gles_crit_sec_.get());

  view_ = (__bridge VideoRenderIosView*)new_window;

  return 0;
}

int VideoRenderIosGles20::StartRender() {
  is_rendering_ = true;
  return 0;
}

int VideoRenderIosGles20::StopRender() {
  is_rendering_ = false;
  return 0;
}

int VideoRenderIosGles20::GetScreenResolution(uint& screen_width,
                                              uint& screen_height) {
  screen_width = [view_ bounds].size.width;
  screen_height = [view_ bounds].size.height;
  return 0;
}

int VideoRenderIosGles20::SetStreamCropping(const uint stream_id,
                                            const float left,
                                            const float top,
                                            const float right,
                                            const float bottom) {
  // Check if there are any updated buffers
  // bool updated = false;
  uint counter = 0;

  std::map<int, VideoRenderIosChannel*>::iterator it = agl_channels_.begin();
  while (it != agl_channels_.end()) {
    if (counter == stream_id) {
      VideoRenderIosChannel* agl_channel = it->second;
      agl_channel->SetStreamSettings(0, left, top, right, bottom);
    }
    counter++;
    it++;
  }

  return 0;
}
