// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/base/upload_data_stream.h"

#include "base/file_util.h"
#include "base/logging.h"
#include "net/base/file_stream.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"

namespace net {

bool UploadDataStream::merge_chunks_ = true;

UploadDataStream::~UploadDataStream() {
}

UploadDataStream* UploadDataStream::Create(UploadData* data, int* error_code) {
  scoped_ptr<UploadDataStream> stream(new UploadDataStream(data));
  int rv = stream->FillBuf();
  if (error_code)
    *error_code = rv;
  if (rv != OK)
    return NULL;

  return stream.release();
}

void UploadDataStream::MarkConsumedAndFillBuffer(size_t num_bytes) {
  DCHECK_LE(num_bytes, buf_len_);
  DCHECK(!eof_);

  if (num_bytes) {
    buf_len_ -= num_bytes;
    if (buf_len_)
      memmove(buf_->data(), buf_->data() + num_bytes, buf_len_);
  }

  FillBuf();

  current_position_ += num_bytes;
}

UploadDataStream::UploadDataStream(UploadData* data)
    : data_(data),
      buf_(new IOBuffer(kBufSize)),
      buf_len_(0),
      next_element_(0),
      next_element_offset_(0),
      next_element_remaining_(0),
      total_size_(data->is_chunked() ? 0 : data->GetContentLength()),
      current_position_(0),
      eof_(false) {
}

int UploadDataStream::FillBuf() {
  std::vector<UploadData::Element>& elements = *data_->elements();

  while (buf_len_ < kBufSize && next_element_ < elements.size()) {
    bool advance_to_next_element = false;

    UploadData::Element& element = elements[next_element_];

    size_t size_remaining = kBufSize - buf_len_;
    if (element.type() == UploadData::TYPE_BYTES ||
        element.type() == UploadData::TYPE_CHUNK) {
      const std::vector<char>& d = element.bytes();
      size_t count = d.size() - next_element_offset_;

      size_t bytes_copied = std::min(count, size_remaining);

      // Check if we have anything to copy first, because we are getting the
      // address of an element in |d| and that will throw an exception if |d|
      // is an empty vector.
      if (bytes_copied) {
        memcpy(buf_->data() + buf_len_, &d[next_element_offset_], bytes_copied);
        buf_len_ += bytes_copied;
      }

      if (bytes_copied == count) {
        advance_to_next_element = true;
      } else {
        next_element_offset_ += bytes_copied;
      }
    } else {
      DCHECK(element.type() == UploadData::TYPE_FILE);

      if (!next_element_remaining_) {
        // If the underlying file has been changed, treat it as error.
        // Note that the expected modification time from WebKit is based on
        // time_t precision. So we have to convert both to time_t to compare.
        if (!element.expected_file_modification_time().is_null()) {
          base::PlatformFileInfo info;
          if (file_util::GetFileInfo(element.file_path(), &info) &&
              element.expected_file_modification_time().ToTimeT() !=
                  info.last_modified.ToTimeT()) {
            return ERR_UPLOAD_FILE_CHANGED;
          }
        }
        next_element_remaining_ = element.GetContentLength();
#ifdef ANDROID
        if (element.file_path().value().find("content://") == 0) {
            next_element_java_stream_.reset(
                new android::JavaISWrapper(element.file_path()));
        } else
#endif
        next_element_stream_.reset(element.NewFileStreamForReading());
      }

      int rv = 0;
      int count =
          static_cast<int>(std::min(next_element_remaining_,
                                    static_cast<uint64>(size_remaining)));
      if (count > 0) {
#ifdef ANDROID
        if (next_element_java_stream_.get())
            rv = next_element_java_stream_->Read(buf_->data() + buf_len_, count);
        else {
#endif
        if (next_element_stream_.get())
          rv = next_element_stream_->Read(buf_->data() + buf_len_, count, NULL);
#ifdef ANDROID
        }
#endif
        if (rv <= 0) {
          // If there's less data to read than we initially observed, then
          // pad with zero.  Otherwise the server will hang waiting for the
          // rest of the data.
          memset(buf_->data() + buf_len_, 0, count);
          rv = count;
        }
        buf_len_ += rv;
      }

      if (static_cast<int>(next_element_remaining_) == rv) {
        advance_to_next_element = true;
      } else {
        next_element_remaining_ -= rv;
      }
    }

    if (advance_to_next_element) {
      ++next_element_;
      next_element_offset_ = 0;
      next_element_remaining_ = 0;
      next_element_stream_.reset();
    }

    if (is_chunked() && !merge_chunks_)
      break;
  }

  if (next_element_ == elements.size() && !buf_len_) {
    if (!data_->is_chunked() ||
        (!elements.empty() && elements.back().is_last_chunk())) {
      eof_ = true;
    }
  }

  return OK;
}

bool UploadDataStream::IsOnLastChunk() const {
  const std::vector<UploadData::Element>& elements = *data_->elements();
  DCHECK(data_->is_chunked());
  return (eof_ ||
          (!elements.empty() &&
           next_element_ == elements.size() &&
           elements.back().is_last_chunk()));
}

}  // namespace net
