// 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 "tink/python/cc/python_output_stream.h"

#include <algorithm>
#include <memory>

#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "tink/output_stream.h"
#include "tink/subtle/subtle_util.h"
#include "tink/util/errors.h"
#include "tink/util/status.h"
#include "tink/util/statusor.h"
#include "tink/python/cc/python_file_object_adapter.h"

namespace crypto {
namespace tink {

PythonOutputStream::PythonOutputStream(
    std::unique_ptr<PythonFileObjectAdapter> adapter, int buffer_size) {
  if (buffer_size <= 0) buffer_size = 128 * 1024;  // 128 KB
  adapter_ = std::move(adapter);
  subtle::ResizeStringUninitialized(&buffer_, buffer_size);
  is_first_call_ = true;
  position_ = 0;
  count_in_buffer_ = 0;
  buffer_offset_ = 0;
  status_ = util::OkStatus();
}

crypto::tink::util::StatusOr<int> PythonOutputStream::Next(void** data) {
  if (!status_.ok()) return status_;

  // This is the first call to Next(), so we return the whole buffer.
  if (is_first_call_) {
    is_first_call_ = false;
    count_in_buffer_ = buffer_.size();
    position_ = buffer_.size();
    *data = &buffer_[0];
    return buffer_.size();
  }

  // If some space was backed up, return it first.
  if (count_in_buffer_ < buffer_.size()) {
    int count_backedup = buffer_.size() - count_in_buffer_;
    position_ += count_backedup;
    buffer_offset_ = count_in_buffer_;
    count_in_buffer_ = buffer_.size();
    *data = &buffer_[buffer_offset_];
    return count_backedup;
  }

  // Write the data from the buffer and return available space in the buffer.
  // The available space might not span the entire buffer, as writing
  // may succeed only for a prefix of the buffer -- in this case the data still
  // to be written is shifted in the buffer and the remaining space is returned.
  auto write_result = adapter_->Write(buffer_);
  if (!write_result.ok()) return status_ = write_result.status();

  // Some data was written, so we can return some portion of buffer_.
  int written = write_result.ValueOrDie();
  position_ += written;
  count_in_buffer_ = buffer_.size();
  buffer_offset_ = buffer_.size() - written;
  if (written < buffer_.size()) {
    // Only part of the data was written, shift the remaining data in buffer_.
    // Using memmove, as source and destination may overlap.
    std::memmove(&buffer_[0], &buffer_[written], buffer_offset_);
  }
  *data = &buffer_[buffer_offset_];
  return written;
}

void PythonOutputStream::BackUp(int count) {
  if (!status_.ok() || count < 1 || count_in_buffer_ == 0) return;
  int actual_count = std::min(count, count_in_buffer_ - buffer_offset_);
  count_in_buffer_ -= actual_count;
  position_ -= actual_count;
}

PythonOutputStream::~PythonOutputStream() { Close().IgnoreError(); }

util::Status PythonOutputStream::Close() {
  if (!status_.ok()) return status_;
  if (count_in_buffer_ > 0) {
    // Try to write the remaining bytes.
    int written = 0;
    while (written < count_in_buffer_) {
      auto write_result = adapter_->Write(absl::string_view(buffer_).substr(
          written, count_in_buffer_ - written));
      if (!write_result.ok()) return write_result.status();
      written += write_result.ValueOrDie();
    }
  }
  status_ = adapter_->Close();
  if (!status_.ok()) return status_;
  status_ = util::Status(util::error::FAILED_PRECONDITION, "Stream closed");
  return util::OkStatus();
}

int64_t PythonOutputStream::Position() const { return position_; }

}  // namespace tink
}  // namespace crypto
