/**
 * Nsmf_PDUSession
 * SMF PDU Session Service. © 2019, 3GPP Organizational Partners (ARIB, ATIS,
 * CCSA, ETSI, TSDSI, TTA, TTC). All rights reserved.
 *
 * The version of the OpenAPI document: 1.1.0.alpha-1
 *
 *
 * NOTE: This class is auto generated by OpenAPI Generator
 * (https://openapi-generator.tech). https://openapi-generator.tech Do not edit
 * the class manually.
 */

/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
 *
 * 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.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

#include "SMContextsCollectionApiImpl.h"
#include "logger.hpp"
#include "smf_msg.hpp"
#include "itti_msg_n11.hpp"
#include "3gpp_29.502.h"
#include <nghttp2/asio_http2_server.h>
#include "smf_config.hpp"
#include "3gpp_conversions.hpp"

extern smf::smf_config smf_cfg;

namespace oai {
namespace smf_server {
namespace api {

using namespace oai::smf_server::model;

SMContextsCollectionApiImpl::SMContextsCollectionApiImpl(
    std::shared_ptr<Pistache::Rest::Router> rtr, smf::smf_app* smf_app_inst,
    std::string address)
    : SMContextsCollectionApi(rtr),
      m_smf_app(smf_app_inst),
      m_address(address) {}

void SMContextsCollectionApiImpl::post_sm_contexts(
    const SmContextMessage& smContextMessage,
    Pistache::Http::ResponseWriter& response) {
  Logger::smf_api_server().info("PDU Session Create SM Context Request.");

  // Create a pdu_session_create_sm_context_request message and store
  // the necessary information
  Logger::smf_api_server().debug(
      "Create a pdu_session_create_sm_context_request message and store the "
      "necessary information");
  smf::pdu_session_create_sm_context_request sm_context_req_msg = {};

  // convert from SmContextMessage to pdu_session_create_sm_context_request
  xgpp_conv::sm_context_create_from_openapi(
      smContextMessage, sm_context_req_msg);

  // Set API Root to be used as location header in HTTP response
  sm_context_req_msg.set_api_root(
      m_address + base + smf_cfg.sbi_api_version +
      NSMF_PDU_SESSION_SM_CONTEXT_CREATE_URL);

  boost::shared_ptr<
      boost::promise<smf::pdu_session_create_sm_context_response> >
      p = boost::make_shared<
          boost::promise<smf::pdu_session_create_sm_context_response> >();
  boost::shared_future<smf::pdu_session_create_sm_context_response> f;
  f = p->get_future();

  // Generate ID for this promise (to be used in SMF-APP)
  uint32_t promise_id = generate_promise_id();
  Logger::smf_api_server().debug("Promise ID generated %d", promise_id);
  m_smf_app->add_promise(promise_id, p);

  // Handle the pdu_session_create_sm_context_request message in smf_app
  std::shared_ptr<itti_n11_create_sm_context_request> itti_msg =
      std::make_shared<itti_n11_create_sm_context_request>(
          TASK_SMF_N11, TASK_SMF_APP, promise_id);
  itti_msg->req          = sm_context_req_msg;
  itti_msg->http_version = 1;
  m_smf_app->handle_pdu_session_create_sm_context_request(itti_msg);

  // Wait for the result from APP and send reply to AMF
  smf::pdu_session_create_sm_context_response sm_context_response = f.get();
  Logger::smf_api_server().debug("Got result for promise ID %d", promise_id);

  nlohmann::json json_data = {};

  response.headers().add<Pistache::Http::Header::Location>(
      sm_context_response.get_smf_context_uri());  // Location header
  sm_context_response.get_json_data(json_data);
  std::string json_format;
  sm_context_response.get_json_format(json_format);
  if (!json_data.empty()) {
    response.headers().add<Pistache::Http::Header::ContentType>(
        Pistache::Http::Mime::MediaType(json_format));
    response.send(
        Pistache::Http::Code(sm_context_response.get_http_code()),
        json_data.dump().c_str());
  } else {
    response.send(Pistache::Http::Code(sm_context_response.get_http_code()));
  }
}
}  // namespace api
}  // namespace smf_server
}  // namespace oai
