/*
 * 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()");
  DETACH_FROM_THREAD(task_runner_thread_checker_);
}

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

void AnimatedWebPImage::Play(
    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
  TRACE_EVENT0("cobalt::loader::image", "AnimatedWebPImage::Play()");
  // This function may be called from a thread that is not the task runner
  // thread, but it must be consistent (and consistent with Stop() also).
  // This ensures that it's safe to set |task_runner_| without holding a lock.
  DCHECK_CALLED_ON_VALID_THREAD(task_runner_thread_checker_);
  if (!task_runner_) {
    task_runner_ = task_runner;
  } else {
    DCHECK_EQ(task_runner_, task_runner);
  }

  task_runner_->PostTask(FROM_HERE, base::Bind(&AnimatedWebPImage::PlayInternal,
                                               base::Unretained(this)));
}

void AnimatedWebPImage::Stop() {
  TRACE_EVENT0("cobalt::loader::image", "AnimatedWebPImage::Stop()");
  // This function may be called from a thread that is not the task runner
  // thread, but it must be consistent (and consistent with Play() also).
  DCHECK_CALLED_ON_VALID_THREAD(task_runner_thread_checker_);
  if (!task_runner_) {
    // The image has not started playing yet.
    return;
  }

  task_runner_->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_) {
      StartDecoding();
    }
  }
  frame_count_ = new_frame_count;
}

AnimatedWebPImage::~AnimatedWebPImage() {
  TRACE_EVENT0("cobalt::loader::image",
               "AnimatedWebPImage::~AnimatedWebPImage()");
  if (task_runner_) {
    Stop();
    task_runner_->WaitForFence();
  }

  WebPDemuxDelete(demux_);
}

void AnimatedWebPImage::PlayInternal() {
  TRACE_EVENT0("cobalt::loader::image", "AnimatedWebPImage::PlayInternal()");
  base::AutoLock lock(lock_);

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

  if (received_first_frame_) {
    StartDecoding();
  }
}

void AnimatedWebPImage::StopInternal() {
  TRACE_EVENT0("cobalt::loader::image", "AnimatedWebPImage::StopInternal()");
  DCHECK(task_runner_->BelongsToCurrentThread());
  base::AutoLock lock(lock_);
  if (!is_playing_) {
    return;
  }

  if (!decode_closure_.callback().is_null()) {
    is_playing_ = false;
    decode_closure_.Cancel();
  }
}

void AnimatedWebPImage::StartDecoding() {
  TRACE_EVENT0("cobalt::loader::image", "AnimatedWebPImage::StartDecoding()");
  lock_.AssertAcquired();
  current_frame_time_ = base::TimeTicks::Now();
  if (task_runner_->BelongsToCurrentThread()) {
    DecodeFrames();
  } else {
    task_runner_->PostTask(FROM_HERE,
                           base::Bind(&AnimatedWebPImage::LockAndDecodeFrames,
                                      base::Unretained(this)));
  }
}

void AnimatedWebPImage::LockAndDecodeFrames() {
  TRACE_EVENT0("cobalt::loader::image",
               "AnimatedWebPImage::LockAndDecodeFrames()");
  DCHECK(task_runner_->BelongsToCurrentThread());

  base::AutoLock lock(lock_);
  DecodeFrames();
}

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

  if (decode_closure_.callback().is_null()) {
    decode_closure_.Reset(
        base::Bind(&AnimatedWebPImage::LockAndDecodeFrames,
                   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;
    }

    task_runner_->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 base::Optional<std::string>& error) {
  if (error) LOG(ERROR) << *error;
}

}  // namespace

bool AnimatedWebPImage::DecodeOneFrame(int frame_index) {
  TRACE_EVENT0("cobalt::loader::image", "AnimatedWebPImage::DecodeOneFrame()");
  TRACK_MEMORY_SCOPE("Rendering");
  DCHECK(task_runner_->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),
        ImageDecoder::kImageTypeWebP, base::Bind(&DecodeError));
    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(task_runner_->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
