// 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 "base/debug/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();
}

scoped_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.Pass();
}

scoped_refptr<Image> ImageDataDecoder::CreateStaticImage(
    scoped_ptr<render_tree::ImageData> image_data) {
  DCHECK(image_data);
  return new StaticImage(resource_provider()->CreateImage(image_data.Pass()));
}

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
