// 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 "cobalt/browser/screen_shot_writer.h"

#include <memory>
#include <utility>

#include "base/basictypes.h"
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/loader/image/image_encoder.h"
#include "cobalt/render_tree/resource_provider_stub.h"

namespace cobalt {
namespace browser {

ScreenShotWriter::ScreenShotWriter(renderer::Pipeline* pipeline)
    : pipeline_(pipeline), screenshot_thread_("ScreenshotIOThd") {
  DCHECK(pipeline);
  screenshot_thread_.Start();
}

void ScreenShotWriter::RequestScreenshotToFile(
    loader::image::EncodedStaticImage::ImageFormat desired_format,
    const base::FilePath& output_path,
    const scoped_refptr<render_tree::Node>& render_tree_root,
    const base::Optional<math::Rect>& clip_rect,
    const base::Closure& complete) {
  base::Callback<void(const scoped_refptr<loader::image::EncodedStaticImage>&)>
      done_encoding_callback =
          base::Bind(&ScreenShotWriter::WriteEncodedImageToFile,
                     base::Unretained(this), output_path, complete);

  renderer::Pipeline::RasterizationCompleteCallback callback =
      base::Bind(&ScreenShotWriter::EncodeData, base::Unretained(this),
                 desired_format, done_encoding_callback);
  RequestScreenshotToMemoryUnencoded(render_tree_root, clip_rect, callback);
}

void ScreenShotWriter::RequestScreenshotToMemoryUnencoded(
    const scoped_refptr<render_tree::Node>& render_tree_root,
    const base::Optional<math::Rect>& clip_rect,
    const renderer::Pipeline::RasterizationCompleteCallback& callback) {
  DCHECK(!callback.is_null());
  if (clip_rect && clip_rect->IsEmpty()) {
    callback.Run(std::unique_ptr<uint8[]>(), math::Size());
  } else {
    pipeline_->RasterizeToRGBAPixels(
        render_tree_root, clip_rect,
        base::Bind(&ScreenShotWriter::RunOnScreenshotThread,
                   base::Unretained(this), callback));
  }
}

void ScreenShotWriter::RequestScreenshotToMemory(
    loader::image::EncodedStaticImage::ImageFormat desired_format,
    const scoped_refptr<render_tree::Node>& render_tree_root,
    const base::Optional<math::Rect>& clip_rect,
    const ScreenShotWriter::ImageEncodeCompleteCallback& screenshot_ready) {
  renderer::Pipeline::RasterizationCompleteCallback callback =
      base::Bind(&ScreenShotWriter::EncodeData, base::Unretained(this),
                 desired_format, screenshot_ready);
  RequestScreenshotToMemoryUnencoded(render_tree_root, clip_rect, callback);
}

void ScreenShotWriter::EncodeData(
    loader::image::EncodedStaticImage::ImageFormat desired_format,
    const base::Callback<
        void(const scoped_refptr<loader::image::EncodedStaticImage>&)>&
        done_encoding_callback,
    std::unique_ptr<uint8[]> pixel_data, const math::Size& image_dimensions) {
  TRACE_EVENT0("cobalt::browser", "ScreenshotWriter::EncodeData()");
  scoped_refptr<loader::image::EncodedStaticImage> image_data;
  if (!image_dimensions.IsEmpty()) {
    image_data = loader::image::CompressRGBAImage(
        desired_format, pixel_data.get(), image_dimensions);
  }
  done_encoding_callback.Run(image_data);
}

void ScreenShotWriter::RunOnScreenshotThread(
    const renderer::Pipeline::RasterizationCompleteCallback& callback,
    std::unique_ptr<uint8[]> image_data, const math::Size& image_dimensions) {
  DCHECK(image_data);

  if (base::MessageLoop::current() != screenshot_thread_.message_loop()) {
    screenshot_thread_.message_loop()->task_runner()->PostTask(
        FROM_HERE, base::Bind(&ScreenShotWriter::RunOnScreenshotThread,
                              base::Unretained(this), callback,
                              base::Passed(&image_data), image_dimensions));
    return;
  }

  callback.Run(std::move(image_data), image_dimensions);
}

void ScreenShotWriter::WriteEncodedImageToFile(
    const base::FilePath& output_path, const base::Closure& complete_callback,
    const scoped_refptr<loader::image::EncodedStaticImage>& image_data) {
  DCHECK_EQ(base::MessageLoop::current(), screenshot_thread_.message_loop());

  // Blocking write to output_path.
  if (!image_data) {
    DLOG(ERROR)
        << "Unable to take screenshot because image data is unavailable.";
  } else {
    int num_bytes = static_cast<int>(image_data->GetEstimatedSizeInBytes());
    int bytes_written = base::WriteFile(
        output_path, reinterpret_cast<char*>(image_data->GetMemory()),
        num_bytes);
    LOG_IF(ERROR, bytes_written != num_bytes)
        << "Error writing screenshot to file.";
  }

  // Notify the caller that the screenshot is complete.
  if (!complete_callback.is_null()) {
    complete_callback.Run();
  }
}

}  // namespace browser
}  // namespace cobalt
