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

#include <algorithm>

#include "base/debug/trace_event.h"

namespace cobalt {
namespace loader {
namespace image {

namespace {
// The capacity of data buffer.
uint32 kMaxBufferSizeBytes = 32 * 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 the data_buffer, so no data append needs to be performed.
      input_bytes = data + offset;
      input_size = size - offset;
      offset += input_size;
    } else {
      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);
    size_t undecoded_size = input_size - decoded_size;

    if (undecoded_size == 0) {
      // Remove all elements from the data_buffer.
      data_buffer_.clear();
    } else {
      data_buffer_.reserve(kMaxBufferSizeBytes);
      if (data_buffer_.empty()) {
        // data_buffer is empty, so assign the undecoded data to it.
        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));
      }
    }
  }
}

bool ImageDataDecoder::FinishWithSuccess() {
  TRACE_EVENT0("cobalt::loader::image_decoder",
               "ImageDataDecoder::FinishWithSuccess");

  FinishInternal();

  if (state_ != kDone) {
    image_data_.reset();
  }

  return state_ == kDone;
}

bool ImageDataDecoder::AllocateImageData(const math::Size& size,
                                         bool has_alpha) {
  DCHECK(resource_provider_->AlphaFormatSupported(
      render_tree::kAlphaFormatOpaque));
  DCHECK(resource_provider_->AlphaFormatSupported(
      render_tree::kAlphaFormatPremultiplied));
  image_data_ = resource_provider_->AllocateImageData(
      size, pixel_format(), has_alpha ? render_tree::kAlphaFormatPremultiplied
                                      : render_tree::kAlphaFormatOpaque);
  if (!image_data_) {
    DLOG(WARNING) << "Failed to allocate image data (" << size.width() << "x"
                  << size.height() << ").";
  }
  return 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
