// 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 {

base::Value NetLogInitEndInfoParams(int result,
                                    int total_size,
                                    bool is_chunked) {
  base::Value dict(base::Value::Type::DICTIONARY);

  dict.SetIntKey("net_error", result);
  dict.SetIntKey("total_size", total_size);
  dict.SetBoolKey("is_chunked", is_chunked);
  return dict;
}

base::Value CreateReadInfoParams(int current_position) {
  base::Value dict(base::Value::Type::DICTIONARY);

  dict.SetIntKey("current_position", current_position);
  return 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,
                      [&] { return CreateReadInfoParams(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 nullptr;
}

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, [&] {
    return NetLogInitEndInfoParams(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
