// Copyright 2016 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/image_data_decoder.h"

#include <algorithm>
#include <memory>

#include "base/trace_event/trace_event.h"

namespace cobalt {
namespace loader {
namespace image {

namespace {
// Sanity check max size of data buffer.
uint32 kMaxBufferSizeBytes = 4 * 1024 * 1024L;
}  // namespace

ImageDataDecoder::ImageDataDecoder(
    render_tree::ResourceProvider* resource_provider)
    : resource_provider_(resource_provider), state_(kWaitingForHeader) {
  CalculatePixelFormat();
}

void ImageDataDecoder::DecodeChunk(const uint8* data, size_t size) {
  TRACE_EVENT0("cobalt::loader::image_decoder",
               "ImageDataDecoder::DecodeChunk");
  size_t offset = 0;
  while (offset < size) {
    if (state_ == kError) {
      // Previous chunk causes an error, so there is nothing to do in here.
      return;
    }

    const uint8* input_bytes;
    size_t input_size;

    if (data_buffer_.empty()) {
      // Nothing in |data_buffer_|, so no data append needs to be performed.
      input_bytes = data + offset;
      input_size = size - offset;
      offset += input_size;
    } else {
      DCHECK_GE(kMaxBufferSizeBytes, data_buffer_.size());
      size_t fill_buffer_size =
          std::min(kMaxBufferSizeBytes - data_buffer_.size(), size - offset);

      // Append new data to data_buffer
      data_buffer_.insert(data_buffer_.end(), data + offset,
                          data + offset + fill_buffer_size);

      input_bytes = &data_buffer_[0];
      input_size = data_buffer_.size();
      offset += fill_buffer_size;
    }

    size_t decoded_size = DecodeChunkInternal(input_bytes, input_size);
    if (decoded_size == 0 && offset < size) {
      LOG(ERROR) << "Unable to make progress decoding image.";
      state_ = kError;
      return;
    }

    size_t undecoded_size = input_size - decoded_size;
    if (undecoded_size == 0) {
      // Remove all elements from the data_buffer.
      data_buffer_.clear();
    } else {
      if (data_buffer_.empty()) {
        if (undecoded_size > kMaxBufferSizeBytes) {
          LOG(ERROR) << "Max buffer size too small: " << undecoded_size
                     << "bytes required!";
          state_ = kError;
          return;
        }

        // |data_buffer_| is empty, so assign the undecoded data to it.
        data_buffer_.reserve(undecoded_size);
        data_buffer_.assign(data + offset - undecoded_size, data + offset);
      } else if (decoded_size != 0) {
        // |data_buffer_| is not empty, so erase the decoded data from it.
        data_buffer_.erase(
            data_buffer_.begin(),
            data_buffer_.begin() + static_cast<ptrdiff_t>(decoded_size));
      }
    }
  }
}

scoped_refptr<Image> ImageDataDecoder::FinishAndMaybeReturnImage() {
  TRACE_EVENT0("cobalt::loader::image_decoder",
               "ImageDataDecoder::FinishAndMaybeReturnImage");

  return FinishInternal();
}

std::unique_ptr<render_tree::ImageData> ImageDataDecoder::AllocateImageData(
    const math::Size& size, bool has_alpha) {
  DCHECK(resource_provider_->AlphaFormatSupported(
      render_tree::kAlphaFormatOpaque));
  DCHECK(resource_provider_->AlphaFormatSupported(
      render_tree::kAlphaFormatPremultiplied));
  auto image_data = resource_provider_->AllocateImageData(
      size, pixel_format(),
      has_alpha ? render_tree::kAlphaFormatPremultiplied
                : render_tree::kAlphaFormatOpaque);
  DLOG_IF(ERROR, !image_data) << "Failed to allocate image data ("
                              << size.width() << "x" << size.height() << ").";
  return image_data;
}

scoped_refptr<Image> ImageDataDecoder::CreateStaticImage(
    std::unique_ptr<render_tree::ImageData> image_data) {
  DCHECK(image_data);
  return new StaticImage(
      resource_provider()->CreateImage(std::move(image_data)));
}

void ImageDataDecoder::CalculatePixelFormat() {
  pixel_format_ = render_tree::kPixelFormatRGBA8;
  if (!resource_provider_->PixelFormatSupported(pixel_format_)) {
    pixel_format_ = render_tree::kPixelFormatBGRA8;
  }

  DCHECK(resource_provider_->PixelFormatSupported(pixel_format_));
}

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