// Copyright 2019 Google Inc.
//
// 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/streamingaead/decrypting_random_access_stream.h"

#include "absl/memory/memory.h"
#include "absl/synchronization/mutex.h"
#include "tink/random_access_stream.h"
#include "tink/primitive_set.h"
#include "tink/streaming_aead.h"
#include "tink/streamingaead/shared_random_access_stream.h"
#include "tink/util/buffer.h"
#include "tink/util/errors.h"
#include "tink/util/status.h"
#include "tink/util/statusor.h"

namespace crypto {
namespace tink {
namespace streamingaead {

using crypto::tink::PrimitiveSet;
using crypto::tink::StreamingAead;
using util::Status;
using util::StatusOr;

// static
StatusOr<std::unique_ptr<RandomAccessStream>> DecryptingRandomAccessStream::New(
    std::shared_ptr<PrimitiveSet<StreamingAead>> primitives,
    std::unique_ptr<crypto::tink::RandomAccessStream> ciphertext_source,
    absl::string_view associated_data) {
  if (primitives == nullptr) {
    return Status(util::error::INVALID_ARGUMENT,
                  "primitives must be non-null.");
  }
  if (ciphertext_source == nullptr) {
    return Status(util::error::INVALID_ARGUMENT,
                  "ciphertext_source must be non-null.");
  }
  return {absl::WrapUnique(new DecryptingRandomAccessStream(
      primitives, std::move(ciphertext_source), associated_data))};
}

util::Status DecryptingRandomAccessStream::PRead(
    int64_t position, int count,
    crypto::tink::util::Buffer* dest_buffer) {
  {  // "fast-track": quickly proceed if matching has been attempted/found.
    if (dest_buffer == nullptr) {
      return util::Status(util::error::INVALID_ARGUMENT,
                          "dest_buffer must be non-null");
    }
    if (count < 0) {
      return util::Status(util::error::INVALID_ARGUMENT,
                          "count cannot be negative");
    }
    if (count > dest_buffer->allocated_size()) {
      return util::Status(util::error::INVALID_ARGUMENT, "buffer too small");
    }
    if (position < 0) {
      return util::Status(util::error::INVALID_ARGUMENT,
                          "position cannot be negative");
    }
    absl::ReaderMutexLock lock(&matching_mutex_);
    if (matching_stream_ != nullptr) {
      return matching_stream_->PRead(position, count, dest_buffer);
    }
    if (attempted_matching_) {
      return Status(util::error::INVALID_ARGUMENT,
                    "Did not find a decrypter matching the ciphertext stream.");
    }
  }
  // Matching has not been attempted yet, so try it now.
  absl::MutexLock lock(&matching_mutex_);

  // Re-check that matching hasn't been attempted in the meantime.
  if (matching_stream_ != nullptr) {
    return matching_stream_->PRead(position, count, dest_buffer);
  }
  if (attempted_matching_) {
    return Status(util::error::INVALID_ARGUMENT,
                  "Did not find a decrypter matching the ciphertext stream.");
  }
  attempted_matching_ = true;
  auto raw_primitives_result = primitives_->get_raw_primitives();
  if (!raw_primitives_result.ok()) {
    return Status(util::error::INTERNAL, "No RAW primitives found");
  }
  for (auto& primitive : *(raw_primitives_result.ValueOrDie())) {
    StreamingAead& streaming_aead = primitive->get_primitive();
    auto shared_ct = absl::make_unique<SharedRandomAccessStream>(
        ciphertext_source_.get());
    auto decrypting_stream_result =
        streaming_aead.NewDecryptingRandomAccessStream(
            std::move(shared_ct), associated_data_);
    if (decrypting_stream_result.ok()) {
      auto status = decrypting_stream_result.ValueOrDie()->PRead(
          position, count, dest_buffer);
      if (status.ok() || status.error_code() == util::error::OUT_OF_RANGE) {
        // Found a match.
        matching_stream_ = std::move(decrypting_stream_result.ValueOrDie());
        return status;
      }
    }
    // Not a match, try the next primitive.
  }
  return Status(util::error::INVALID_ARGUMENT,
                "Could not find a decrypter matching the ciphertext stream.");
}

StatusOr<int64_t> DecryptingRandomAccessStream::size() {
  absl::ReaderMutexLock lock(&matching_mutex_);
  if (matching_stream_ != nullptr) {
    return matching_stream_->size();
  }
  // TODO(b/139722894): attempt matching here?
  return Status(util::error::UNAVAILABLE, "no matching found yet");
}

}  // namespace streamingaead
}  // namespace tink
}  // namespace crypto
