/*
 * Copyright 2016 Google Inc. 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/threaded_image_decoder_proxy.h"

#include <string>

#include "base/bind.h"
#include "base/threading/thread.h"
#include "cobalt/loader/image/image_decoder.h"

namespace cobalt {
namespace loader {
namespace image {

namespace {

// Helper function that is run on the WebModule thread to run a Callback if
// and only if |threaded_image_decoder_proxy| is still alive.
template <typename Callback, typename Arg>
void MaybeRun(
    base::WeakPtr<ThreadedImageDecoderProxy> threaded_image_decoder_proxy,
    const Callback& callback, const Arg& arg) {
  if (threaded_image_decoder_proxy) {
    callback.Run(arg);
  }
}

// Helper function to post a Callback back to the WebModule thread, that
// checks whether the ThreadedImageDecoderProxy it came from is alive or not
// before it runs.
template <typename Callback, typename Arg>
void PostToMessageLoopChecked(
    base::WeakPtr<ThreadedImageDecoderProxy> threaded_image_decoder_proxy,
    const Callback& callback, MessageLoop* message_loop, const Arg& arg) {
  message_loop->PostTask(
      FROM_HERE, base::Bind(&MaybeRun<Callback, Arg>,
                            threaded_image_decoder_proxy, callback, arg));
}

}  // namespace

ThreadedImageDecoderProxy::ThreadedImageDecoderProxy(
    render_tree::ResourceProvider* resource_provider,
    const SuccessCallback& success_callback,
    const ErrorCallback& error_callback,
    MessageLoop* software_decode_loop,
    MessageLoop* hardware_decode_loop)
    : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
      ALLOW_THIS_IN_INITIALIZER_LIST(
          weak_this_(weak_ptr_factory_.GetWeakPtr())),
      software_decode_loop_(software_decode_loop),
      hardware_decode_loop_(hardware_decode_loop),
      result_message_loop_(MessageLoop::current()),
      image_decoder_(new ImageDecoder(
          resource_provider,
          base::Bind(
              &PostToMessageLoopChecked<SuccessCallback,
                                        scoped_refptr<render_tree::Image> >,
              weak_this_, success_callback, result_message_loop_),
          base::Bind(&PostToMessageLoopChecked<ErrorCallback, std::string>,
                     weak_this_, error_callback, result_message_loop_))) {
  DCHECK(software_decode_loop_);
  DCHECK(hardware_decode_loop_);
  DCHECK(result_message_loop_);
  DCHECK(image_decoder_);
}

// We're dying, but |image_decoder_| might still be doing work on the load
// thread.  Because of this, we transfer ownership of it into the load message
// loop, where it will be deleted after any pending tasks involving it are
// done.
ThreadedImageDecoderProxy::~ThreadedImageDecoderProxy() {
  MessageLoop* decode_loop = GetDecodeLoop();
  decode_loop->DeleteSoon(FROM_HERE, image_decoder_.release());
}

LoadResponseType ThreadedImageDecoderProxy::OnResponseStarted(
    Fetcher* fetcher, const scoped_refptr<net::HttpResponseHeaders>& headers) {
  UNREFERENCED_PARAMETER(fetcher);
  return image_decoder_->OnResponseStarted(fetcher, headers);
}

void ThreadedImageDecoderProxy::DecodeChunk(const char* data, size_t size) {
  if (image_decoder_->EnsureDecoderIsInitialized(data, size)) {
    if (IsLoadMessageLoopCurrent()) {
      image_decoder_->DecodeChunk(data, size);
    } else {
      scoped_ptr<std::string> scoped_data(new std::string(data, size));
      GetDecodeLoop()->PostTask(
          FROM_HERE, base::Bind(&Decoder::DecodeChunkPassed,
                                base::Unretained(image_decoder_.get()),
                                base::Passed(&scoped_data)));
    }
  }
}

void ThreadedImageDecoderProxy::DecodeChunkPassed(
    scoped_ptr<std::string> data) {
  if (image_decoder_->EnsureDecoderIsInitialized(data->data(), data->size())) {
    if (IsLoadMessageLoopCurrent()) {
      image_decoder_->DecodeChunkPassed(data.Pass());
    } else {
      GetDecodeLoop()->PostTask(
          FROM_HERE, base::Bind(&Decoder::DecodeChunkPassed,
                                base::Unretained(image_decoder_.get()),
                                base::Passed(&data)));
    }
  }
}

void ThreadedImageDecoderProxy::Finish() {
  if (IsLoadMessageLoopCurrent()) {
    image_decoder_->Finish();
  } else {
    GetDecodeLoop()->PostTask(
        FROM_HERE, base::Bind(&ImageDecoder::Finish,
                              base::Unretained(image_decoder_.get())));
  }
}

bool ThreadedImageDecoderProxy::Suspend() {
  GetDecodeLoop()->PostTask(
      FROM_HERE, base::Bind(base::IgnoreResult(&ImageDecoder::Suspend),
                            base::Unretained(image_decoder_.get())));
  return true;
}

void ThreadedImageDecoderProxy::Resume(
    render_tree::ResourceProvider* resource_provider) {
  GetDecodeLoop()->PostTask(
      FROM_HERE,
      base::Bind(&ImageDecoder::Resume, base::Unretained(image_decoder_.get()),
                 resource_provider));
}

MessageLoop* ThreadedImageDecoderProxy::GetDecodeLoop() const {
  DCHECK(image_decoder_);
  return image_decoder_->IsHardwareDecoder() ? hardware_decode_loop_ :
                                               software_decode_loop_;
}

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