// Copyright 2016 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 "algorithms/forculus/forculus_analyzer.h"

#include <glog/logging.h>

#include "algorithms/forculus/forculus_utils.h"
#include "util/crypto_util/base64.h"
#include "util/log_based_metrics.h"

namespace cobalt {
namespace forculus {

// Stackdriver metric constants
namespace {
const char kAddObservationFailure[] =
    "forculus-analyzer-add-observation-failure";
}  // namespace

namespace {
// Produces a string used in an error message to describe the observation.
std::string ErrorString(const ForculusObservation& obs) {
  std::string ciphertext;
  std::string point_x;
  std::string point_y;
  crypto::Base64Encode(obs.ciphertext(), &ciphertext);
  crypto::Base64Encode(obs.point_x(), &point_x);
  crypto::Base64Encode(obs.point_y(), &point_y);
  return "ciphertext=" + ciphertext + " x=" + point_x + " y=" + point_y;
}

}  // namespace

ForculusAnalyzer::ForculusAnalyzer(const cobalt::ForculusConfig& config)
    : config_(config) {}

bool ForculusAnalyzer::AddObservation(uint32_t day_index,
                                      const ForculusObservation& obs) {
  // Compute the epoch_index from the day_index.
  uint32_t epoch_index =
      EpochIndexFromDayIndex(day_index, config_.epoch_type());

  // Look in decryption_map for our (day_index, obs) pair.
  DecrypterGroupKey group_key(epoch_index, obs.ciphertext());
  auto decryption_map_iter = decryption_map_.find(group_key);

  if (decryption_map_iter == decryption_map_.end()) {
    // There was no entry for this group_key in decryption_map. Create a
    // new ForculusDecrypter and a new entry.
    std::unique_ptr<ForculusDecrypter> decrypter(
        new ForculusDecrypter(config_.threshold(), obs.ciphertext()));
    decrypter->AddObservation(obs);
    decryption_map_.emplace(group_key, DecrypterResult(std::move(decrypter)));
  } else {
    // There is already an entry in encryption map.
    DecrypterResult& decrypter_result = decryption_map_iter->second;
    if (decrypter_result.result_info) {
      // The ciphertext has already been decrypted. Just increment the count.
      decrypter_result.result_info->total_count++;
    } else {
      // The ciphertext has not yet been decrypted. Add this additional
      // observation and let's see if that pushes us over the threshold.
      if (!decrypter_result.decrypter) {
        // We have previously deleted the decrypter object because it was
        // in an inconsistent state.
        LOG_STACKDRIVER_COUNT_METRIC(ERROR, kAddObservationFailure)
            << "Skipping decryption because of a previous error: "
            << "day_index=" << day_index << " " << ErrorString(obs);
        observation_errors_++;
        return false;
      }
      if (decrypter_result.decrypter->AddObservation(obs) !=
          ForculusDecrypter::kOK) {
        // Delete the Decrypter object. It is in an inconsistent state.
        LOG_STACKDRIVER_COUNT_METRIC(ERROR, kAddObservationFailure)
            << "Found inconsistent observation. Deleting Decrypter: "
            << ErrorString(obs);
        decrypter_result.decrypter.reset();
        observation_errors_++;
        return false;
      }
      if (decrypter_result.decrypter->size() >= config_.threshold()) {
        // We are now able to decrypt the ciphertext.
        std::string recovered_text;
        if (decrypter_result.decrypter->Decrypt(&recovered_text) !=
            ForculusDecrypter::kOK) {
          // Delete the Decrypter object. It is in an inconsistent state.
          LOG_STACKDRIVER_COUNT_METRIC(ERROR, kAddObservationFailure)
              << "Decryption failed. Deleting Decrypter: " << ErrorString(obs);
          decrypter_result.decrypter.reset();
          observation_errors_++;
          return false;
        }
        uint32_t num_seen = decrypter_result.decrypter->num_seen();

        // Delete the Decrypter object. It has done its job and we don't need
        // it anymore.
        VLOG(4) << "Decryption succeeded: '" << recovered_text
                << "' Deleting Decrypter: day_index=" << day_index << " "
                << ErrorString(obs);
        decrypter_result.decrypter.reset();
        auto results_iter = results_.find(recovered_text);
        if (results_iter == results_.end()) {
          // This is the first time this recovered_text has been seen. Make
          // a new ResultInfo.
          std::unique_ptr<ResultInfo> result_info(new ResultInfo(num_seen));
          // Keep a non-owned pointer to result_info in the decrypter_map
          // so we can find it quickly the next time we get another observation
          // with the same group_key.
          decrypter_result.result_info = result_info.get();
          // Keep the owned pointer in results_.
          results_.emplace(std::move(recovered_text), std::move(result_info));
        } else {
          // This recovered text has been seen before. This happens when
          // we are analyzing more than one Forculus epoch and this same
          // recovered text was seen in a different epoch.
          auto& result_info = results_iter->second;
          result_info->num_epochs++;
          result_info->total_count += num_seen;
          // Keep a non-owned pointer to result_info in the decrypter_map
          // so we can find it quickly the next time we get another observation
          // with the same group_key.
          decrypter_result.result_info = result_info.get();
        }
      }
    }
  }
  num_observations_++;
  return true;
}

size_t ForculusAnalyzer::KeyHasher::operator()(
    const DecrypterGroupKey& key) const {
  // The probability of having the same ciphertext with two different
  // epoch_indexes is negligably small since the epoch_index was one of
  // the ingredients that went into the master key during encryption. For
  // this reason we use the hash of the ciphertext alone as the hash of the
  // pair.
  return std::hash<std::string>()(key.ciphertext);
}

}  // namespace forculus
}  // namespace cobalt
