// Copyright (c) 2012 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_file_element_reader.h"

#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/profiler/scoped_tracker.h"
#include "base/task_runner_util.h"
#include "net/base/file_stream.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"

namespace net {

namespace {

// In tests, this value is used to override the return value of
// UploadFileElementReader::GetContentLength() when set to non-zero.
uint64 overriding_content_length = 0;

}  // namespace

UploadFileElementReader::UploadFileElementReader(
    base::TaskRunner* task_runner,
    const base::FilePath& path,
    uint64 range_offset,
    uint64 range_length,
    const base::Time& expected_modification_time)
    : task_runner_(task_runner),
      path_(path),
      range_offset_(range_offset),
      range_length_(range_length),
      expected_modification_time_(expected_modification_time),
      content_length_(0),
      bytes_remaining_(0),
      weak_ptr_factory_(this) {
  DCHECK(task_runner_.get());
}

UploadFileElementReader::~UploadFileElementReader() {
}

const UploadFileElementReader* UploadFileElementReader::AsFileReader() const {
  return this;
}

int UploadFileElementReader::Init(const CompletionCallback& callback) {
  DCHECK(!callback.is_null());
  Reset();

  file_stream_.reset(new FileStream(task_runner_.get()));
  int result = file_stream_->Open(
      path_,
      base::File::FLAG_OPEN | base::File::FLAG_READ |
      base::File::FLAG_ASYNC,
      base::Bind(&UploadFileElementReader::OnOpenCompleted,
                 weak_ptr_factory_.GetWeakPtr(),
                 callback));
  DCHECK_GT(0, result);
  return result;
}

uint64 UploadFileElementReader::GetContentLength() const {
  if (overriding_content_length)
    return overriding_content_length;
  return content_length_;
}

uint64 UploadFileElementReader::BytesRemaining() const {
  return bytes_remaining_;
}

int UploadFileElementReader::Read(IOBuffer* buf,
                                  int buf_length,
                                  const CompletionCallback& callback) {
  DCHECK(!callback.is_null());

  int num_bytes_to_read = static_cast<int>(
      std::min(BytesRemaining(), static_cast<uint64>(buf_length)));
  if (num_bytes_to_read == 0)
    return 0;

  int result = file_stream_->Read(
      buf, num_bytes_to_read,
      base::Bind(base::IgnoreResult(&UploadFileElementReader::OnReadCompleted),
                 weak_ptr_factory_.GetWeakPtr(),
                 callback));
  // Even in async mode, FileStream::Read() may return the result synchronously.
  if (result != ERR_IO_PENDING)
    return OnReadCompleted(CompletionCallback(), result);
  return ERR_IO_PENDING;
}

void UploadFileElementReader::Reset() {
  weak_ptr_factory_.InvalidateWeakPtrs();
  bytes_remaining_ = 0;
  content_length_ = 0;
  file_stream_.reset();
}

void UploadFileElementReader::OnOpenCompleted(
    const CompletionCallback& callback,
    int result) {
  // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed.
  tracked_objects::ScopedTracker tracking_profile(
      FROM_HERE_WITH_EXPLICIT_FUNCTION(
          "423948 UploadFileElementReader::OnOpenCompleted"));

  DCHECK(!callback.is_null());

  if (result < 0) {
    DLOG(WARNING) << "Failed to open \"" << path_.value()
                  << "\" for reading: " << result;
    callback.Run(result);
    return;
  }

  if (range_offset_) {
    int result = file_stream_->Seek(
        base::File::FROM_BEGIN, range_offset_,
        base::Bind(&UploadFileElementReader::OnSeekCompleted,
                   weak_ptr_factory_.GetWeakPtr(),
                   callback));
    DCHECK_GT(0, result);
    if (result != ERR_IO_PENDING)
      callback.Run(result);
  } else {
    OnSeekCompleted(callback, OK);
  }
}

void UploadFileElementReader::OnSeekCompleted(
    const CompletionCallback& callback,
    int64 result) {
  DCHECK(!callback.is_null());

  if (result < 0) {
    DLOG(WARNING) << "Failed to seek \"" << path_.value()
                  << "\" to offset: " << range_offset_ << " (" << result << ")";
    callback.Run(static_cast<int>(result));
    return;
  }

  base::File::Info* file_info = new base::File::Info;
  bool posted = base::PostTaskAndReplyWithResult(
      task_runner_.get(),
      FROM_HERE,
      base::Bind(&base::GetFileInfo, path_, file_info),
      base::Bind(&UploadFileElementReader::OnGetFileInfoCompleted,
                 weak_ptr_factory_.GetWeakPtr(),
                 callback,
                 base::Owned(file_info)));
  DCHECK(posted);
}

void UploadFileElementReader::OnGetFileInfoCompleted(
    const CompletionCallback& callback,
    base::File::Info* file_info,
    bool result) {
  DCHECK(!callback.is_null());
  if (!result) {
    DLOG(WARNING) << "Failed to get file info of \"" << path_.value() << "\"";
    callback.Run(ERR_FILE_NOT_FOUND);
    return;
  }

  int64 length = file_info->size;
  if (range_offset_ < static_cast<uint64>(length)) {
    // Compensate for the offset.
    length = std::min(length - range_offset_, range_length_);
  }

  // If the underlying file has been changed and the expected file modification
  // time is set, treat it as error. Note that |expected_modification_time_| may
  // have gone through multiple conversion steps involving loss of precision
  // (including conversion to time_t). Therefore the check below only verifies
  // that the timestamps are within one second of each other. This check is used
  // for sliced files.
  if (!expected_modification_time_.is_null() &&
      (expected_modification_time_ - file_info->last_modified)
              .magnitude()
              .InSeconds() != 0) {
    callback.Run(ERR_UPLOAD_FILE_CHANGED);
    return;
  }

  content_length_ = length;
  bytes_remaining_ = GetContentLength();
  callback.Run(OK);
}

int UploadFileElementReader::OnReadCompleted(
    const CompletionCallback& callback,
    int result) {
  if (result == 0)  // Reached end-of-file earlier than expected.
    result = ERR_UPLOAD_FILE_CHANGED;

  if (result > 0) {
    DCHECK_GE(bytes_remaining_, static_cast<uint64>(result));
    bytes_remaining_ -= result;
  }

  if (!callback.is_null())
    callback.Run(result);
  return result;
}

UploadFileElementReader::ScopedOverridingContentLengthForTests::
ScopedOverridingContentLengthForTests(uint64 value) {
  overriding_content_length = value;
}

UploadFileElementReader::ScopedOverridingContentLengthForTests::
~ScopedOverridingContentLengthForTests() {
  overriding_content_length = 0;
}

}  // namespace net
