/*
 * Copyright 2023 Google LLC
 *
 * 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 "event_store.h"

#include <cstddef>
#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "absl/base/thread_annotations.h"
#include "absl/container/btree_set.h"
#include "absl/synchronization/mutex.h"
#include "subscription.h"
#include "nlohmann/json.hpp"

namespace ecclesia {

namespace {

// Stores JSON formatted Redfish Event with associated unique identifier.
// The Redfish Event schema is based on standard defined at
// http://redfish.dmtf.org/schemas/v1/Event.v1_9_0.json with OEM extensions.
struct EventContext {
  EventContext(const EventId &event_id, const nlohmann::json &event)
      : event_id(event_id), event(event) {}

  EventId event_id;
  nlohmann::json event;
};

struct TimestampComparator {
  bool operator()(const EventContext &a, const EventContext &b) const {
    return a.event_id.timestamp < b.event_id.timestamp;
  }
};

class EventStoreImpl : public EventStore {
 public:
  explicit EventStoreImpl(size_t store_size) : store_size_(store_size) {}

  void AddNewEvent(const EventId &event_id,
                   const nlohmann::json &event) override {
    absl::MutexLock lock(&event_contexts_mutex_);
    if (event_contexts_.size() == store_size_) {
      event_contexts_.erase(event_contexts_.begin());
    }

    event_contexts_.insert(EventContext(event_id, event));
  }

  // Retrieves all events that have been added since the given
  // `redfish_event_id` in chronological order based on event timestamp.
  std::vector<nlohmann::json> GetEventsSince(
      std::optional<size_t> redfish_event_id) override {
    absl::MutexLock lock(&event_contexts_mutex_);

    // Return all events when last_event_id is not provided
    std::vector<nlohmann::json> events_to_return = {};
    if (!redfish_event_id.has_value()) {
      for (const auto &context : event_contexts_) {
        events_to_return.push_back(context.event);
      }
      return events_to_return;
    }

    // Stores subscription id of the `redfish_event_id` which will be used to
    // find related events so that subscriber gets only the events it previously
    // subscribed for.
    std::optional<SubscriptionId> subscription_id;

    for (auto it = event_contexts_.begin(); it != event_contexts_.end(); ++it) {
      if (subscription_id.has_value() &&
          it->event_id.subscription_id == subscription_id.value()) {
        events_to_return.push_back(it->event);
      }
      if (it->event_id.redfish_event_id == redfish_event_id.value()) {
        subscription_id = it->event_id.subscription_id;
      }
    }

    return events_to_return;
  }

  nlohmann::json GetEvent(const EventId &event_id) override {
    absl::MutexLock lock(&event_contexts_mutex_);
    for (auto it = event_contexts_.begin(); it != event_contexts_.end(); ++it) {
      if (it->event_id == event_id) {
        return it->event;
      }
    }
    return {};
  }

  std::vector<nlohmann::json> GetEventsBySubscriptionId(
      const size_t subscription_id) override {
    std::vector<nlohmann::json> events_to_return = {};
    absl::MutexLock lock(&event_contexts_mutex_);
    for (auto it = event_contexts_.begin(); it != event_contexts_.end(); ++it) {
      if (it->event_id.subscription_id.Id() == subscription_id) {
        events_to_return.push_back(it->event);
      }
    }
    return events_to_return;
  }

  nlohmann::json ToJSON() override {
    nlohmann::json json;
    nlohmann::json& events_json = json["EventStore"];
    events_json = nlohmann::json::array();
    absl::MutexLock lock(&event_contexts_mutex_);
    for (auto it = event_contexts_.begin(); it != event_contexts_.end(); ++it) {
      nlohmann::json event;
      event["EventId"] = it->event_id.ToJSON();
      event["Event"] = it->event;
      events_json.push_back(event);
    }
    json["NumEvents"] = events_json.size();
    return json;
  }

  // Converts EventStore to string format
  std::string ToString() override { return ToJSON().dump(); }

  // Clear all events
  void Clear() override {
    absl::MutexLock lock(&event_contexts_mutex_);
    event_contexts_.clear();
  }

 private:
  absl::Mutex event_contexts_mutex_;
  absl::btree_multiset<EventContext, TimestampComparator> event_contexts_
      ABSL_GUARDED_BY(event_contexts_mutex_);
  size_t store_size_;
};

}  // namespace

std::unique_ptr<EventStore> CreateEventStore(size_t store_size) {
  return std::make_unique<EventStoreImpl>(store_size);
}

}  // namespace ecclesia
