#ifndef THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_TASK_H_
#define THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_TASK_H_

/*
// Copyright (c) 2020 Intel Corporation
//
// 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 <algorithm>
#include <array>
#include <chrono>  // NOLINT
#include <cstddef>
#include <ctime>
#include <deque>
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <utility>

#include "boost/asio/post.hpp"  // NOLINT
#include "boost/asio/steady_timer.hpp"  // NOLINT
#include "app.hpp"
#include "http_request.hpp"
#include "http_response.hpp"
#include "logging.hpp"
#include "parsing.hpp"
#include "utility.hpp"
#include "async_resp.hpp"
#include "error_messages.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "task_messages.hpp"
#include "time_utils.hpp"
#include "health.hpp"
#include <nlohmann/json.hpp>
#include "managed_store.hpp"
#include "sdbusplus/bus.hpp"
#include "sdbusplus/bus/match.hpp"
#include "sdbusplus/message.hpp"

#ifdef UNIT_TEST_BUILD
#include "test/g3/mock_managed_store.hpp"  // NOLINT
#endif

namespace redfish {

namespace task {
constexpr size_t maxTaskCount = 100;  // arbitrary limit

// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
static std::deque<std::shared_ptr<struct TaskData>> tasks;

constexpr bool completed = true;

struct Payload {
  explicit Payload(const crow::Request& req)
      : targetUri(req.url().encoded_path()),
        httpOperation(req.methodString()),
        httpHeaders(nlohmann::json::array()) {
    using field_ns = boost::beast::http::field;
    constexpr const std::array<boost::beast::http::field, 7> headerWhitelist = {
        field_ns::accept, field_ns::accept_encoding, field_ns::user_agent,
        field_ns::host,   field_ns::connection,      field_ns::content_length,
        field_ns::upgrade};

    JsonParseResult ret = parseRequestAsJson(req, jsonBody);
    if (ret != JsonParseResult::Success) {
      return;
    }

    for (const auto& field : req.fields()) {
      if (std::find(headerWhitelist.begin(), headerWhitelist.end(),
                    field.name()) == headerWhitelist.end()) {
        continue;
      }
      std::string header;
      header.reserve(field.name_string().size() + 2 + field.value().size());
      header += field.name_string();
      header += ": ";
      header += field.value();
      httpHeaders.emplace_back(std::move(header));
    }
  }
  Payload() = delete;

  std::string targetUri;
  std::string httpOperation;
  nlohmann::json httpHeaders;
  nlohmann::json jsonBody;
};

struct TaskData : std::enable_shared_from_this<TaskData> {
 private:
  TaskData(std::function<bool(boost::system::error_code, sdbusplus::message_t&,
                              const std::shared_ptr<TaskData>&)>&& handler,
           const std::string& matchIn, size_t idx)
      : callback(std::move(handler)),
        matchStr(matchIn),
        index(idx),
        startTime(std::chrono::system_clock::to_time_t(
            std::chrono::system_clock::now())),
        status("OK"),
        state("Running"),
        messages(nlohmann::json::array()),
        timer(managedStore::GetManagedObjectStore()->GetIoContext())

  {}

 public:
  TaskData() = delete;

  static std::shared_ptr<TaskData>& createTask(
      std::function<bool(boost::system::error_code, sdbusplus::message_t&,
                         const std::shared_ptr<TaskData>&)>&& handler,
      const std::string& match) {
    static size_t lastTask = 0;
    struct MakeSharedHelper : public TaskData {
      MakeSharedHelper(
          std::function<bool(boost::system::error_code, sdbusplus::message_t&,
                             const std::shared_ptr<TaskData>&)>&& handler,
          const std::string& match2, size_t idx)
          : TaskData(std::move(handler), match2, idx) {}
    };

    if (tasks.size() >= maxTaskCount) {
      const auto& last = tasks.front();

      // destroy all references
      last->timer.cancel();
      last->match.reset();
      tasks.pop_front();
    }

    return tasks.emplace_back(std::make_shared<MakeSharedHelper>(
        std::move(handler), match, lastTask++));
  }

  void populateResp(crow::Response& res, size_t retryAfterSeconds = 30) {
    if (!endTime) {
      res.result(boost::beast::http::status::accepted);
      std::string strIdx = std::to_string(index);
      std::string uri = "/redfish/v1/TaskService/Tasks/" + strIdx;

      res.jsonValue["@odata.id"] = uri;
      res.jsonValue["@odata.type"] = "#Task.v1_4_3.Task";
      res.jsonValue["Id"] = strIdx;
      res.jsonValue["TaskState"] = state;
      res.jsonValue["TaskStatus"] = status;

      res.addHeader(boost::beast::http::field::location, uri + "/Monitor");
      res.addHeader(boost::beast::http::field::retry_after,
                    std::to_string(retryAfterSeconds));
    } else if (!gaveResult) {
      if (result) {
        res.jsonValue = *result;
      }
      res.result(resultHttpStatus);
      gaveResult = true;
    }
  }

  void finishTask() {
    endTime =
        std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
  }

  void extendTimer(const std::chrono::seconds& timeout) {
    timer.expires_after(timeout);
    timer.async_wait([self = shared_from_this()](boost::system::error_code ec) {
      if (ec == boost::asio::error::operation_aborted) {
        return;  // completed successfully
      }
      if (!ec) {
        // change ec to error as timer expired
        ec = boost::asio::error::operation_aborted;
      }
      self->match.reset();
      sdbusplus::message_t msg;
      self->finishTask();
      self->state = "Cancelled";
      self->status = "Warning";
      self->messages.emplace_back(
          messages::taskAborted(std::to_string(self->index)));
      self->callback(ec, msg, self);
    });
  }


  // Can be called manually by task handlers implementing asynchronous
  // completion. They must also call stopMonitor().
  void complete() {
    timer.cancel();
    finishTask();

  }

  void complete(nlohmann::json&& outputResult,
                boost::beast::http::status httpStatus) {
    result = std::move(outputResult);
    resultHttpStatus = httpStatus;
    complete();
  }

  // Stop watching for property changes. Only required to be called by users
  // when handling calling complete() manually too.
  void stopMonitor() {
    boost::asio::post(managedStore::GetManagedObjectStore()->GetIoContext(),
                      [self = shared_from_this()] { self->match.reset(); });
  }

  void startTimer(const std::chrono::seconds& timeout) {
    if (match) {
      return;
    }
    match = std::make_unique<sdbusplus::bus::match_t>(
        static_cast<sdbusplus::bus_t&>(
            *(managedStore::GetManagedObjectStore()
                  ->GetDeprecatedThreadUnsafeSystemBus())),
        matchStr, [self = shared_from_this()](sdbusplus::message_t& message) {
          boost::system::error_code ec;

          // callback to return True if callback is done, callback needs
          // to update status itself if needed
          if (self->callback(ec, message, self) == task::completed) {
            self->complete();
            self->stopMonitor();
          }
        });

    extendTimer(timeout);
    messages.emplace_back(messages::taskStarted(std::to_string(index)));
  }

  std::function<bool(boost::system::error_code, sdbusplus::message_t&,
                     const std::shared_ptr<TaskData>&)>
      callback;
  std::string matchStr;
  size_t index;
  time_t startTime;
  std::string status;
  std::string state;
  nlohmann::json messages;
  boost::asio::steady_timer timer;
  std::unique_ptr<sdbusplus::bus::match_t> match;
  std::optional<time_t> endTime;
  std::optional<Payload> payload;
  std::optional<nlohmann::json> result;
  boost::beast::http::status resultHttpStatus =
      boost::beast::http::status::no_content;
  bool gaveResult = false;
  int percentComplete = 0;
};

}  // namespace task

inline void handleGetTaskMonitor(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& strParam) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  auto find =
      std::find_if(task::tasks.begin(), task::tasks.end(),
                   [&strParam](const std::shared_ptr<task::TaskData>& task) {
                     if (!task) {
                       return false;
                     }

                     // we compare against the string version as on failure
                     // strtoul returns 0
                     return std::to_string(task->index) == strParam;
                   });

  if (find == task::tasks.end()) {
    messages::resourceNotFound(asyncResp->res, "Task", strParam);
    return;
  }
  std::shared_ptr<task::TaskData>& ptr = *find;
  // monitor expires after result
  if (ptr->gaveResult) {
    messages::resourceNotFound(asyncResp->res, "Task", strParam);
    return;
  }
  ptr->populateResp(asyncResp->res);
}

inline void requestRoutesTaskMonitor(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/TaskService/Tasks/<str>/Monitor/")
      .privileges(redfish::privileges::getTask)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleGetTaskMonitor, std::ref(app)));
}

inline void handleGetTask(App& app, const crow::Request& req,
                          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                          const std::string& strParam) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  auto find =
      std::find_if(task::tasks.begin(), task::tasks.end(),
                   [&strParam](const std::shared_ptr<task::TaskData>& task) {
                     if (!task) {
                       return false;
                     }

                     // we compare against the string version as on failure
                     // strtoul returns 0
                     return std::to_string(task->index) == strParam;
                   });

  if (find == task::tasks.end()) {
    messages::resourceNotFound(asyncResp->res, "Task", strParam);
    return;
  }

  const std::shared_ptr<task::TaskData>& ptr = *find;

  asyncResp->res.jsonValue["@odata.type"] = "#Task.v1_4_3.Task";
  asyncResp->res.jsonValue["Id"] = strParam;
  asyncResp->res.jsonValue["Name"] = "Task " + strParam;
  asyncResp->res.jsonValue["TaskState"] = ptr->state;
  asyncResp->res.jsonValue["StartTime"] =
      redfish::time_utils::getDateTimeStdtime(ptr->startTime);
  if (ptr->endTime) {
    asyncResp->res.jsonValue["EndTime"] =
        redfish::time_utils::getDateTimeStdtime(*(ptr->endTime));
  }
  asyncResp->res.jsonValue["TaskStatus"] = ptr->status;
  asyncResp->res.jsonValue["Messages"] = ptr->messages;
  asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
      "redfish", "v1", "TaskService", "Tasks", strParam);
  if (!ptr->gaveResult) {
    asyncResp->res.jsonValue["TaskMonitor"] =
        "/redfish/v1/TaskService/Tasks/" + strParam + "/Monitor";
  }
  if (ptr->payload) {
    const task::Payload& p = *(ptr->payload);
    asyncResp->res.jsonValue["Payload"]["TargetUri"] = p.targetUri;
    asyncResp->res.jsonValue["Payload"]["HttpOperation"] = p.httpOperation;
    asyncResp->res.jsonValue["Payload"]["HttpHeaders"] = p.httpHeaders;
    asyncResp->res.jsonValue["Payload"]["JsonBody"] =
        p.jsonBody.dump(2, ' ', true, nlohmann::json::error_handler_t::replace);
  }
  asyncResp->res.jsonValue["PercentComplete"] = ptr->percentComplete;
}

inline void requestRoutesTask(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/TaskService/Tasks/<str>/")
      .privileges(redfish::privileges::getTask)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleGetTask, std::ref(app)));
}

inline void handleGetTaskCollection(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  asyncResp->res.jsonValue["@odata.type"] = "#TaskCollection.TaskCollection";
  asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/TaskService/Tasks";
  asyncResp->res.jsonValue["Name"] = "Task Collection";
  nlohmann::json& members = asyncResp->res.jsonValue["Members"];
  if (!members.is_array()) {
    // With Redfish aggregation, top level collections can have their
    // Members array already created if a satellite response has been
    // processed first.  In that case we don't want to clobber the
    // aggregated data
    members = nlohmann::json::array();
  }

  for (const std::shared_ptr<task::TaskData>& task : task::tasks) {
    if (task == nullptr) {
      continue;  // shouldn't be possible
    }
    nlohmann::json::object_t member;
    member["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "TaskService", "Tasks", std::to_string(task->index));
    members.emplace_back(std::move(member));
  }
  asyncResp->res.jsonValue["Members@odata.count"] = members.size();
}

inline void requestRoutesTaskCollection(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/TaskService/Tasks/")
      .privileges(redfish::privileges::getTaskCollection)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleGetTaskCollection, std::ref(app)));
}

inline void handleGetTaskService(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  asyncResp->res.jsonValue["@odata.type"] = "#TaskService.v1_1_4.TaskService";
  asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/TaskService";
  asyncResp->res.jsonValue["Name"] = "Task Service";
  asyncResp->res.jsonValue["Id"] = "TaskService";
  asyncResp->res.jsonValue["DateTime"] =
      redfish::time_utils::getDateTimeOffsetNow().first;
  asyncResp->res.jsonValue["CompletedTaskOverWritePolicy"] = "Oldest";

  asyncResp->res.jsonValue["LifeCycleEventOnTaskStateChange"] = true;

#ifdef HEALTH_POPULATE
  auto health = std::make_shared<HealthPopulate>(asyncResp);
  health->populate();
#endif
  asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
  asyncResp->res.jsonValue["ServiceEnabled"] = true;
  asyncResp->res.jsonValue["Tasks"]["@odata.id"] =
      "/redfish/v1/TaskService/Tasks";
}

inline void requestRoutesTaskService(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/TaskService/")
      .privileges(redfish::privileges::getTaskService)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleGetTaskService, std::ref(app)));
}

}  // namespace redfish

#endif  // THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_TASK_H_
