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

#include "base/logging.h"
#include "base/values.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/log/net_log_event_type.h"

namespace net {

namespace {

std::unique_ptr<base::Value> NetLogInitEndInfoCallback(
    int result,
    int total_size,
    bool is_chunked,
    NetLogCaptureMode /* capture_mode */) {
  std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());

  dict->SetInteger("net_error", result);
  dict->SetInteger("total_size", total_size);
  dict->SetBoolean("is_chunked", is_chunked);
  return std::move(dict);
}

std::unique_ptr<base::Value> NetLogReadInfoCallback(
    int current_position,
    NetLogCaptureMode /* capture_mode */) {
  std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());

  dict->SetInteger("current_position", current_position);
  return std::move(dict);
}

}  // namespace

UploadDataStream::UploadDataStream(bool is_chunked, int64_t identifier)
    : total_size_(0),
      current_position_(0),
      identifier_(identifier),
      is_chunked_(is_chunked),
      initialized_successfully_(false),
      is_eof_(false) {
}

UploadDataStream::~UploadDataStream() = default;

int UploadDataStream::Init(CompletionOnceCallback callback,
                           const NetLogWithSource& net_log) {
  Reset();
  DCHECK(!initialized_successfully_);
  DCHECK(callback_.is_null());
  DCHECK(!callback.is_null() || IsInMemory());
  net_log_ = net_log;
  net_log_.BeginEvent(NetLogEventType::UPLOAD_DATA_STREAM_INIT);

  int result = InitInternal(net_log_);
  if (result == ERR_IO_PENDING) {
    DCHECK(!IsInMemory());
    callback_ = std::move(callback);
  } else {
    OnInitCompleted(result);
  }

  return result;
}

int UploadDataStream::Read(IOBuffer* buf,
                           int buf_len,
                           CompletionOnceCallback callback) {
  DCHECK(!callback.is_null() || IsInMemory());
  DCHECK(initialized_successfully_);
  DCHECK_GT(buf_len, 0);

  net_log_.BeginEvent(NetLogEventType::UPLOAD_DATA_STREAM_READ,
                      base::Bind(&NetLogReadInfoCallback, current_position_));

  int result = 0;
  if (!is_eof_)
    result = ReadInternal(buf, buf_len);

  if (result == ERR_IO_PENDING) {
    DCHECK(!IsInMemory());
    callback_ = std::move(callback);
  } else {
    OnReadCompleted(result);
  }

  return result;
}

bool UploadDataStream::IsEOF() const {
  DCHECK(initialized_successfully_);
  DCHECK(is_chunked_ || is_eof_ == (current_position_ == total_size_));
  return is_eof_;
}

void UploadDataStream::Reset() {
  // If there's a pending callback, there's a pending init or read call that is
  // being canceled.
  if (!callback_.is_null()) {
    if (!initialized_successfully_) {
      // If initialization has not yet succeeded, this call is aborting
      // initialization.
      net_log_.EndEventWithNetErrorCode(
          NetLogEventType::UPLOAD_DATA_STREAM_INIT, ERR_ABORTED);
    } else {
      // Otherwise, a read is being aborted.
      net_log_.EndEventWithNetErrorCode(
          NetLogEventType::UPLOAD_DATA_STREAM_READ, ERR_ABORTED);
    }
  }

  current_position_ = 0;
  initialized_successfully_ = false;
  is_eof_ = false;
  total_size_ = 0;
  callback_.Reset();
  ResetInternal();
}

void UploadDataStream::SetSize(uint64_t size) {
  DCHECK(!initialized_successfully_);
  DCHECK(!is_chunked_);
  total_size_ = size;
}

void UploadDataStream::SetIsFinalChunk() {
  DCHECK(initialized_successfully_);
  DCHECK(is_chunked_);
  DCHECK(!is_eof_);
  is_eof_ = true;
}

bool UploadDataStream::IsInMemory() const {
  return false;
}

const std::vector<std::unique_ptr<UploadElementReader>>*
UploadDataStream::GetElementReaders() const {
  return NULL;
}

void UploadDataStream::OnInitCompleted(int result) {
  DCHECK_NE(ERR_IO_PENDING, result);
  DCHECK(!initialized_successfully_);
  DCHECK_EQ(0u, current_position_);
  DCHECK(!is_eof_);

  if (result == OK) {
    initialized_successfully_ = true;
    if (!is_chunked_ && total_size_ == 0)
      is_eof_ = true;
  }

  net_log_.EndEvent(
      NetLogEventType::UPLOAD_DATA_STREAM_INIT,
      base::Bind(&NetLogInitEndInfoCallback, result, total_size_, is_chunked_));

  if (!callback_.is_null())
    std::move(callback_).Run(result);
}

void UploadDataStream::OnReadCompleted(int result) {
  DCHECK(initialized_successfully_);
  DCHECK(result != 0 || is_eof_);
  DCHECK_NE(ERR_IO_PENDING, result);

  if (result > 0) {
    current_position_ += result;
    if (!is_chunked_) {
      DCHECK_LE(current_position_, total_size_);
      if (current_position_ == total_size_)
        is_eof_ = true;
    }
  }

  net_log_.EndEventWithNetErrorCode(NetLogEventType::UPLOAD_DATA_STREAM_READ,
                                    result);

  if (!callback_.is_null())
    std::move(callback_).Run(result);
}

UploadProgress UploadDataStream::GetUploadProgress() const {
  // While initialization / rewinding is in progress, return nothing.
  if (!initialized_successfully_)
    return UploadProgress();

  return UploadProgress(current_position_, total_size_);
}

}  // namespace net
