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

#include "base/bind.h"
#include "base/file_util.h"
#include "cobalt/renderer/test/png_utils/png_encode.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkPixelRef.h"

using cobalt::renderer::test::png_utils::EncodeRGBAToBuffer;

namespace cobalt {
namespace browser {
namespace {
scoped_array<uint8> WriteRGBAPixelsToPNG(scoped_array<uint8> pixel_data,
                                         const math::Size& dimensions,
                                         size_t* out_num_bytes) {
  // Given a chunk of memory formatted as RGBA8 with pitch = width * 4, this
  // function will wrap that memory in a SkBitmap that does *not* own the
  // pixels and return that.
  const int kRGBABytesPerPixel = 4;
  SkBitmap bitmap;
  bitmap.installPixels(
      SkImageInfo::Make(dimensions.width(), dimensions.height(),
                        kRGBA_8888_SkColorType, kUnpremul_SkAlphaType),
      const_cast<uint8_t*>(pixel_data.get()),
      dimensions.width() * kRGBABytesPerPixel);

  // No conversion needed here, simply write out the pixels as is.
  return EncodeRGBAToBuffer(static_cast<uint8_t*>(bitmap.pixelRef()->pixels()),
                            bitmap.width(), bitmap.height(),
                            static_cast<int>(bitmap.rowBytes()), out_num_bytes);
}
}  // namespace

ScreenShotWriter::ScreenShotWriter(renderer::Pipeline* pipeline)
    : pipeline_(pipeline),
      screenshot_thread_("Screenshot IO thread") {
  base::Thread::Options options;
  options.message_loop_type = MessageLoop::TYPE_IO;
  screenshot_thread_.StartWithOptions(options);
}

void ScreenShotWriter::RequestScreenshot(const FilePath& output_path,
                                         const base::Closure& complete) {
  RequestScreenshotToMemory(base::Bind(&ScreenShotWriter::EncodingComplete,
                                       base::Unretained(this), output_path,
                                       complete));
}

void ScreenShotWriter::RequestScreenshotToMemory(
    const PNGEncodeCompleteCallback& callback) {
  DCHECK(!callback.is_null());
  DCHECK(last_submission_);
  renderer::Submission submission(last_submission_.value());
  submission.time_offset +=
      base::TimeTicks::HighResNow() - last_submission_time_;
  pipeline_->RasterizeToRGBAPixels(
      submission, base::Bind(&ScreenShotWriter::RasterizationComplete,
                             base::Unretained(this), callback));
}

void ScreenShotWriter::SetLastPipelineSubmission(
    const renderer::Submission& submission) {
  DCHECK(submission.render_tree.get());
  last_submission_ = submission;
  last_submission_time_ = base::TimeTicks::HighResNow();
}

void ScreenShotWriter::ClearLastPipelineSubmission() {
  last_submission_ = base::nullopt;
}

void ScreenShotWriter::RasterizationComplete(
    const PNGEncodeCompleteCallback& encode_complete_callback,
    scoped_array<uint8> pixel_data, const math::Size& dimensions) {
  if (MessageLoop::current() != screenshot_thread_.message_loop()) {
    screenshot_thread_.message_loop()->PostTask(
        FROM_HERE, base::Bind(&ScreenShotWriter::RasterizationComplete,
                              base::Unretained(this), encode_complete_callback,
                              base::Passed(&pixel_data), dimensions));
    return;
  }
  size_t num_bytes;
  scoped_array<uint8> png_data =
      WriteRGBAPixelsToPNG(pixel_data.Pass(), dimensions, &num_bytes);

  encode_complete_callback.Run(png_data.Pass(), num_bytes);
}

void ScreenShotWriter::EncodingComplete(const FilePath& output_path,
                                        const base::Closure& complete_callback,
                                        scoped_array<uint8> png_data,
                                        size_t num_bytes) {
  DCHECK_EQ(MessageLoop::current(), screenshot_thread_.message_loop());
  // Blocking write to output_path.
  int bytes_written =
      file_util::WriteFile(output_path, reinterpret_cast<char*>(png_data.get()),
                           static_cast<int>(num_bytes));
  DLOG_IF(ERROR, bytes_written != num_bytes) << "Error writing PNG to file.";

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

}  // namespace browser
}  // namespace cobalt
