// Copyright 2017 The Fuchsia Authors
//
// 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 "encoder/envelope_maker.h"

#include <utility>

#include "./logging.h"

namespace cobalt {
namespace encoder {

EnvelopeMaker::EnvelopeMaker(const std::string& analyzer_public_key_pem,
                             EncryptedMessage::EncryptionScheme analyzer_scheme,
                             const std::string& shuffler_public_key_pem,
                             EncryptedMessage::EncryptionScheme shuffler_scheme,
                             size_t max_bytes_each_observation,
                             size_t max_num_bytes)
    : encrypt_to_analyzer_(analyzer_public_key_pem, analyzer_scheme),
      encrypt_to_shuffler_(shuffler_public_key_pem, shuffler_scheme),
      max_bytes_each_observation_(max_bytes_each_observation),
      max_num_bytes_(max_num_bytes) {}

EnvelopeMaker::AddStatus EnvelopeMaker::AddObservation(
    const Observation& observation,
    std::unique_ptr<ObservationMetadata> metadata) {
  EncryptedMessage encrypted_message;
  if (encrypt_to_analyzer_.Encrypt(observation, &encrypted_message)) {
    // "+1" below is for the |scheme| field of EncryptedMessage.
    size_t obs_size = encrypted_message.ciphertext().size() +
                      encrypted_message.public_key_fingerprint().size() + 1;
    if (obs_size > max_bytes_each_observation_) {
      VLOG(1) << "WARNING: An Observation was rejected by "
                 "EnvelopeMaker::AddObservation() because it was too big: "
              << obs_size;
      return kObservationTooBig;
    }

    size_t new_num_bytes = num_bytes_ + obs_size;
    if (new_num_bytes > max_num_bytes_) {
      VLOG(4) << "Envelope full.";
      return kEnvelopeFull;
    }

    num_bytes_ = new_num_bytes;
    // Put the encrypted observation into the appropriate ObservationBatch.
    GetBatch(std::move(metadata))
        ->add_encrypted_observation()
        ->Swap(&encrypted_message);
    return kOk;
  } else {
    VLOG(1)
        << "ERROR: Encryption of Observations failed! Observation not added "
           "to batch.";
    return kEncryptionFailed;
  }
}

ObservationBatch* EnvelopeMaker::GetBatch(
    std::unique_ptr<ObservationMetadata> metadata) {
  // Serialize metadata.
  std::string serialized_metadata;
  (*metadata).SerializeToString(&serialized_metadata);

  // See if metadata is already in batch_map_. If so return it.
  auto iter = batch_map_.find(serialized_metadata);
  if (iter != batch_map_.end()) {
    return iter->second;
  }

  // Create a new ObservationBatch and add it to both envelope_ and batch_map_.
  ObservationBatch* observation_batch = envelope_.add_batch();
  observation_batch->set_allocated_meta_data(metadata.release());
  batch_map_[serialized_metadata] = observation_batch;
  return observation_batch;
}

bool EnvelopeMaker::MakeEncryptedEnvelope(
    EncryptedMessage* encrypted_message) const {
  if (!encrypt_to_shuffler_.Encrypt(envelope_, encrypted_message)) {
    VLOG(1) << "ERROR: Encryption of Envelope to the Shuffler failed!";
    return false;
  }
  return true;
}

void EnvelopeMaker::MergeOutOf(EnvelopeMaker* other) {
  CHECK(other);
  // Iterate through the other's batch_map_. For each pair...
  for (auto& other_pair : other->batch_map_) {
    // see if we have a pair with the same key.
    auto iter = batch_map_.find(other_pair.first);
    if (iter != batch_map_.end()) {
      // We do have a pair with the same key. Move the EncryptedMessages
      // from the other's batch into our batch. Note that this process
      // reverses the order of the messages in other but the order of
      // the messages in a batch has no meaning so this doesn't matter.
      auto* other_messages = other_pair.second->mutable_encrypted_observation();
      auto* this_messages = iter->second->mutable_encrypted_observation();
      while (!other_messages->empty()) {
        this_messages->AddAllocated(other_messages->ReleaseLast());
      }
    } else {
      // We do not have a pair with the same key. Make one and swap the
      // contents of the others batch into it.
      ObservationBatch* observation_batch = envelope_.add_batch();
      observation_batch->Swap(other_pair.second);
      batch_map_[other_pair.first] = observation_batch;
    }
  }
  num_bytes_ += other->num_bytes_;
  other->Clear();
}

}  // namespace encoder
}  // namespace cobalt
