/*
 * 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 "subscription.h"

#include <functional>
#include <string>
#include <utility>

#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/hash/hash.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "nlohmann/json.hpp"

namespace ecclesia {

// EventSourceId definitions

nlohmann::json EventSourceId::ToJSON() const {
  nlohmann::json json;
  json["key"] = key;
  switch (type) {
    case Type::kDbusObjects:
      json["type"] = "kDbusObjects";
      break;
    case Type::kSocketIO:
      json["type"] = "kSocketIO";
      break;
    case Type::kFileIO:
      json["type"] = "kFileIO";
      break;
  }
  return json;
}

std::string EventSourceId::ToString() const { return this->ToJSON().dump(); }

// EventId definitions.

EventId::EventId(const SubscriptionId& subscription_id_in,
                 const EventSourceId& source_id_in, absl::Time timestamp_in)
    : source_id(source_id_in),
      timestamp(timestamp_in),
      subscription_id(subscription_id_in),
      redfish_event_id(
          absl::HashOf(timestamp_in, source_id_in, subscription_id_in)) {}

nlohmann::json EventId::ToJSON() const {
  nlohmann::json json;
  json["source_id"] = source_id.ToJSON();
  json["timestamp"] =
      absl::FormatTime(absl::RFC3339_full, timestamp, absl::UTCTimeZone());
  json["uuid"] = redfish_event_id;
  return json;
}

std::string EventId::ToString() const { return this->ToJSON().dump(); }

// SubscriptionContext definitions.

SubscriptionContext::SubscriptionContext(
    const SubscriptionId& subscription_id_in,
    const absl::flat_hash_map<EventSourceId, absl::flat_hash_set<std::string>>&
        event_source_to_uris_in,
    absl::flat_hash_map<std::string, Trigger> id_to_triggers_in,
    std::function<void(const nlohmann::json&)>&& on_event_callback_in)
    : subscription_id(subscription_id_in),
      event_source_to_uri(event_source_to_uris_in),
      id_to_triggers(std::move(id_to_triggers_in)),
      on_event_callback(std::move(on_event_callback_in)) {}

// Trigger definitions.

absl::StatusOr<Trigger> Trigger::Create(const nlohmann::json& trigger_json) {
  // Check if json is valid.
  if (trigger_json.is_discarded()) {
    return absl::InvalidArgumentError("Trigger json is discarded");
  }

  // Parse the JSON data
  auto find_id = trigger_json.find("Id");
  if (find_id == trigger_json.end()) {
    return absl::InvalidArgumentError("Trigger Id not populated");
  }
  // Extract trigger information from the JSON data
  const std::string id = find_id->get<std::string>();

  auto find_origin_resources = trigger_json.find("OriginResources");
  if (find_origin_resources == trigger_json.end()) {
    return absl::InvalidArgumentError("Origin resources not populated");
  }

  absl::flat_hash_set<std::string> origin_resources;
  for (const auto& origin_resource : *find_origin_resources) {
    origin_resources.insert(origin_resource["@odata.id"].get<std::string>());
  }

  std::string predicate;
  bool event_mask = false;

  auto find_predicate = trigger_json.find("Predicate");
  if (find_predicate != trigger_json.end()) {
    predicate = *find_predicate;
  } else {
    // If predicate is not provided, this trigger will be used to poll data.
    // TODO(rahulkpr): Handle the polling case after adding trigger associations
    event_mask = true;
  }

  // Create a Trigger object with the extracted information
  Trigger trigger(id, std::move(origin_resources), predicate, event_mask);

  return trigger;
}

Trigger::Trigger(absl::string_view id_in,
                 absl::flat_hash_set<std::string> origin_resources_in,
                 absl::string_view predicate_in, bool mask_in)
    : id(id_in),
      origin_resources(std::move(origin_resources_in)),
      predicate(predicate_in),
      mask(mask_in) {}

nlohmann::json Trigger::ToJSON() const {
  nlohmann::json json;

  // Create json array and store all origin_resources
  nlohmann::json& origin_resources_json = json["origin_resources"];
  origin_resources_json = nlohmann::json::array();
  origin_resources_json.insert_iterator(origin_resources_json.end(),
                                        origin_resources.begin(),
                                        origin_resources.end());
  json["predicate"] = predicate;
  json["mask"] = mask;
  return json;
}

std::string Trigger::ToString() const { return this->ToJSON().dump(); }

}  // namespace ecclesia
