/*
 * Copyright 2017 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 "cobalt/loader/image/animated_webp_image.h"

#include <string>

#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/loader/image/image_decoder.h"
#include "cobalt/render_tree/brush.h"
#include "cobalt/render_tree/clear_rect_node.h"
#include "cobalt/render_tree/composition_node.h"
#include "cobalt/render_tree/image_node.h"
#include "cobalt/render_tree/node.h"
#include "cobalt/render_tree/rect_node.h"
#include "nb/memory_scope.h"
#include "starboard/memory.h"

namespace cobalt {
namespace loader {
namespace image {
namespace {

const int kLoopInfinite = 0;
const int kMinimumDelayInMilliseconds = 10;

}  // namespace

AnimatedWebPImage::AnimatedWebPImage(
    const math::Size& size, bool is_opaque,
    render_tree::ResourceProvider* resource_provider)
    : size_(size),
      is_opaque_(is_opaque),
      demux_(NULL),
      demux_state_(WEBP_DEMUX_PARSING_HEADER),
      received_first_frame_(false),
      is_playing_(false),
      frame_count_(0),
      loop_count_(kLoopInfinite),
      current_frame_index_(0),
      should_dispose_previous_frame_to_background_(false),
      resource_provider_(resource_provider),
      frame_provider_(new FrameProvider()) {
  TRACE_EVENT0("cobalt::loader::image",
               "AnimatedWebPImage::AnimatedWebPImage()");
}

scoped_refptr<AnimatedImage::FrameProvider>
AnimatedWebPImage::GetFrameProvider() {
  TRACE_EVENT0("cobalt::loader::image",
               "AnimatedWebPImage::GetFrameProvider()");
  return frame_provider_;
}

void AnimatedWebPImage::Play(
    const scoped_refptr<base::MessageLoopProxy>& message_loop) {
  TRACE_EVENT0("cobalt::loader::image", "AnimatedWebPImage::Play()");
  base::AutoLock lock(lock_);

  if (is_playing_) {
    return;
  }
  is_playing_ = true;

  message_loop_ = message_loop;
  if (received_first_frame_) {
    PlayInternal();
  }
}

void AnimatedWebPImage::Stop() {
  TRACE_EVENT0("cobalt::loader::image", "AnimatedWebPImage::Stop()");
  base::AutoLock lock(lock_);
  if (is_playing_) {
    message_loop_->PostTask(
        FROM_HERE,
        base::Bind(&AnimatedWebPImage::StopInternal, base::Unretained(this)));
  }
}

void AnimatedWebPImage::AppendChunk(const uint8* data, size_t size) {
  TRACE_EVENT0("cobalt::loader::image", "AnimatedWebPImage::AppendChunk()");
  TRACK_MEMORY_SCOPE("Rendering");
  base::AutoLock lock(lock_);

  data_buffer_.insert(data_buffer_.end(), data, data + size);
  WebPData webp_data = {&data_buffer_[0], data_buffer_.size()};
  WebPDemuxDelete(demux_);
  demux_ = WebPDemuxPartial(&webp_data, &demux_state_);
  DCHECK_GT(demux_state_, WEBP_DEMUX_PARSING_HEADER);

  // Update frame count.
  int new_frame_count = WebPDemuxGetI(demux_, WEBP_FF_FRAME_COUNT);
  if (new_frame_count > 0 && frame_count_ == 0) {
    // We've just received the first frame.

    received_first_frame_ = true;
    loop_count_ = WebPDemuxGetI(demux_, WEBP_FF_LOOP_COUNT);

    // The default background color of the canvas in [Blue, Green, Red, Alpha],
    // from most significant byte to least significant byte.
    uint32_t background_color = WebPDemuxGetI(demux_, WEBP_FF_BACKGROUND_COLOR);
    background_color_ =
        render_tree::ColorRGBA((background_color >> 8 & 0xff) / 255.0f,
                               (background_color >> 16 & 0xff) / 255.0f,
                               (background_color >> 24 & 0xff) / 255.0f,
                               (background_color >> 0 & 0xff) / 255.0f);

    if (is_playing_) {
      PlayInternal();
    }
  }
  frame_count_ = new_frame_count;
}

AnimatedWebPImage::~AnimatedWebPImage() {
  TRACE_EVENT0("cobalt::loader::image",
               "AnimatedWebPImage::~AnimatedWebPImage()");
  Stop();
  bool is_playing = false;
  {
    base::AutoLock lock(lock_);
    is_playing = is_playing_;
  }
  if (is_playing) {
    message_loop_->WaitForFence();
  }
  WebPDemuxDelete(demux_);
}

void AnimatedWebPImage::StopInternal() {
  TRACE_EVENT0("cobalt::loader::image", "AnimatedWebPImage::StopInternal()");
  DCHECK(message_loop_->BelongsToCurrentThread());
  base::AutoLock lock(lock_);
  if (!decode_closure_.callback().is_null()) {
    is_playing_ = false;
    decode_closure_.Cancel();
  }
}

void AnimatedWebPImage::PlayInternal() {
  TRACE_EVENT0("cobalt::loader::image", "AnimatedWebPImage::PlayInternal()");
  current_frame_time_ = base::TimeTicks::Now();
  message_loop_->PostTask(
      FROM_HERE,
      base::Bind(&AnimatedWebPImage::DecodeFrames, base::Unretained(this)));
}

void AnimatedWebPImage::DecodeFrames() {
  TRACE_EVENT0("cobalt::loader::image", "AnimatedWebPImage::DecodeFrames()");
  TRACK_MEMORY_SCOPE("Rendering");
  DCHECK(is_playing_ && received_first_frame_);
  DCHECK(message_loop_->BelongsToCurrentThread());

  base::AutoLock lock(lock_);

  if (decode_closure_.callback().is_null()) {
    decode_closure_.Reset(
        base::Bind(&AnimatedWebPImage::DecodeFrames, base::Unretained(this)));
  }

  if (AdvanceFrame()) {
    // Decode the frames from current frame to next frame and blend the results.
    DecodeOneFrame(current_frame_index_);
  }

  // Set up the next time to call the decode callback.
  if (is_playing_) {
    const base::TimeDelta min_delay =
        base::TimeDelta::FromMilliseconds(kMinimumDelayInMilliseconds);
    base::TimeDelta delay;
    if (next_frame_time_) {
      delay = *next_frame_time_ - base::TimeTicks::Now();
      if (delay < min_delay) {
        delay = min_delay;
      }
    } else {
      delay = min_delay;
    }

    message_loop_->PostDelayedTask(FROM_HERE, decode_closure_.callback(),
                                   delay);
  }
}

namespace {

void RecordImage(scoped_refptr<render_tree::Image>* image_pointer,
                 const scoped_refptr<loader::image::Image>& image) {
  image::StaticImage* static_image =
      base::polymorphic_downcast<loader::image::StaticImage*>(image.get());
  DCHECK(static_image);
  *image_pointer = static_image->image();
}

void DecodeError(const std::string& error) {
  LOG(ERROR) << error;
}

}  // namespace

bool AnimatedWebPImage::DecodeOneFrame(int frame_index) {
  TRACE_EVENT0("cobalt::loader::image", "AnimatedWebPImage::DecodeOneFrame()");
  TRACK_MEMORY_SCOPE("Rendering");
  DCHECK(message_loop_->BelongsToCurrentThread());
  lock_.AssertAcquired();

  WebPIterator webp_iterator;
  scoped_refptr<render_tree::Image> next_frame_image;

  // Decode the current frame.
  {
    TRACE_EVENT0("cobalt::loader::image", "Decoding");

    WebPDemuxGetFrame(demux_, frame_index, &webp_iterator);
    if (!webp_iterator.complete) {
      return false;
    }

    ImageDecoder image_decoder(
        resource_provider_, base::Bind(&RecordImage, &next_frame_image),
        base::Bind(&DecodeError), ImageDecoder::kImageTypeWebP);
    image_decoder.DecodeChunk(
        reinterpret_cast<const char*>(webp_iterator.fragment.bytes),
        webp_iterator.fragment.size);
    image_decoder.Finish();
    if (!next_frame_image) {
      LOG(ERROR) << "Failed to decode WebP image frame.";
      return false;
    }
  }

  // Alpha blend the current frame on top of the buffer.
  {
    TRACE_EVENT0("cobalt::loader::image", "Blending");

    render_tree::CompositionNode::Builder builder;
    // Add the current canvas or, if there is not one, a background color
    // rectangle;
    if (current_canvas_) {
      builder.AddChild(new render_tree::ImageNode(current_canvas_));
    } else {
      builder.AddChild(new render_tree::ClearRectNode(math::RectF(size_),
                                                      background_color_));
    }
    // Dispose previous frame by adding a solid rectangle.
    if (should_dispose_previous_frame_to_background_) {
      builder.AddChild(new render_tree::ClearRectNode(previous_frame_rect_,
                                                      background_color_));
    }

    // Add the current frame.
    if (webp_iterator.blend_method == WEBP_MUX_NO_BLEND) {
      // If blending is disabled, first clear the image region to transparent
      // before rendering.
      builder.AddChild(new render_tree::ClearRectNode(
          math::RectF(
              math::PointF(webp_iterator.x_offset, webp_iterator.y_offset),
              next_frame_image->GetSize()),
          render_tree::ColorRGBA(0, 0, 0, 0)));
    }

    builder.AddChild(new render_tree::ImageNode(
        next_frame_image,
        math::Vector2dF(webp_iterator.x_offset, webp_iterator.y_offset)));

    scoped_refptr<render_tree::Node> root =
        new render_tree::CompositionNode(builder);

    current_canvas_ = resource_provider_->DrawOffscreenImage(root);
    frame_provider_->SetFrame(current_canvas_);
  }

  if (webp_iterator.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
    should_dispose_previous_frame_to_background_ = true;
    previous_frame_rect_ =
        math::RectF(webp_iterator.x_offset, webp_iterator.y_offset,
                    webp_iterator.width, webp_iterator.height);
  } else if (webp_iterator.dispose_method == WEBP_MUX_DISPOSE_NONE) {
    should_dispose_previous_frame_to_background_ = false;
  } else {
    NOTREACHED();
  }

  WebPDemuxReleaseIterator(&webp_iterator);
  return true;
}

bool AnimatedWebPImage::AdvanceFrame() {
  TRACE_EVENT0("cobalt::loader::image", "AnimatedWebPImage::AdvanceFrame()");
  TRACK_MEMORY_SCOPE("Rendering");
  DCHECK(message_loop_->BelongsToCurrentThread());
  lock_.AssertAcquired();

  base::TimeTicks current_time = base::TimeTicks::Now();

  // If the WebP image hasn't been fully fetched, then stop on the current
  // frame.
  if (demux_state_ == WEBP_DEMUX_PARSED_HEADER) {
    return false;
  }

  // If we're done playing the animation, do nothing.
  if (LoopingFinished()) {
    return false;
  }

  // If it's still not time to advance to the next frame, do nothing.
  if (next_frame_time_ && current_time < *next_frame_time_) {
    return false;
  }

  // Always wait for a consumer to consume the previous frame before moving
  // forward with decoding the next frame.
  if (!frame_provider_->FrameConsumed()) {
    return false;
  }

  if (next_frame_time_) {
    current_frame_time_ = *next_frame_time_;
  } else {
    current_frame_time_ = current_time;
  }

  ++current_frame_index_;
  if (current_frame_index_ == frame_count_) {
    // Check if we have finished looping, and if so return indicating that there
    // is no additional frame available.
    if (LoopingFinished()) {
      next_frame_time_ = base::nullopt;
      return false;
    }

    // Loop around to the beginning
    current_frame_index_ = 0;
    if (loop_count_ != kLoopInfinite) {
      loop_count_--;
    }
  }

  // Update the time in the future at which point we should switch to the
  // frame after the new current frame.
  next_frame_time_ =
      current_frame_time_ + GetFrameDuration(current_frame_index_);
  if (next_frame_time_ < current_time) {
    // Don't let the animation fall back for more than a frame.
    next_frame_time_ = current_time;
  }

  return true;
}

base::TimeDelta AnimatedWebPImage::GetFrameDuration(int frame_index) {
  lock_.AssertAcquired();
  WebPIterator webp_iterator;
  WebPDemuxGetFrame(demux_, frame_index, &webp_iterator);
  base::TimeDelta frame_duration =
      base::TimeDelta::FromMilliseconds(webp_iterator.duration);
  WebPDemuxReleaseIterator(&webp_iterator);
  return frame_duration;
}

bool AnimatedWebPImage::LoopingFinished() const {
  return loop_count_ == 1 && current_frame_index_ == frame_count_;
}

}  // namespace image
}  // namespace loader
}  // namespace cobalt
