/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 "strategy.h"
#include "consistenthash.h"
#include "util.h"

#include <cinttypes>
#include <string>
#include <algorithm>
#include <mutex>
#include <unordered_map>
#include <unordered_set>
#include <fstream>
#include <cstring>

#include <sys/stat.h>
#include <dirent.h>

#include <yaml-cpp/yaml.h>

#include "tscore/HashSip.h"
#include "tscore/ConsistentHash.h"
#include "tscore/ink_assert.h"
#include "ts/ts.h"
#include "ts/remap.h"
#include "ts/parentselectdefs.h"

void
PLNextHopHealthStatus::insert(std::vector<std::shared_ptr<PLHostRecord>> &hosts)
{
  for (uint32_t ii = 0; ii < hosts.size(); ii++) {
    std::shared_ptr<PLHostRecord> h = hosts[ii];
    for (auto protocol = h->protocols.begin(); protocol != h->protocols.end(); ++protocol) {
      const std::string host_port = h->getHostPort((*protocol)->port);
      host_map.emplace(std::make_pair(host_port, h));
      PL_NH_Debug(PL_NH_DEBUG_TAG, "inserting %s into host_map", host_port.c_str());
    }
  }
}

void
PLNextHopHealthStatus::mark(TSHttpTxn txnp, PLStatusTxn *state, const char *hostname, const size_t hostname_len,
                            const in_port_t port, const PLNHCmd status, const time_t now)
{
  const time_t _now = now == 0 ? time(nullptr) : now;

  const int64_t sm_id = TSHttpTxnIdGet(txnp);

  int64_t fail_threshold; //  = sm->t_state.txn_conf->parent_fail_threshold;
  if (TSHttpTxnConfigIntGet(txnp, TS_CONFIG_HTTP_PARENT_PROXY_FAIL_THRESHOLD, &fail_threshold) != TS_SUCCESS) {
    PL_NH_Error("mark failed to get parent_fail_threshold, cannot mark next hop");
    return;
  }

  int64_t retry_time; //      = sm->t_state.txn_conf->parent_retry_time;
  if (TSHttpTxnConfigIntGet(txnp, TS_CONFIG_HTTP_PARENT_PROXY_RETRY_TIME, &retry_time) != TS_SUCCESS) {
    PL_NH_Error("mark failed to get parent_retry_time, cannot mark next hop");
    return;
  }

  uint32_t new_fail_count = 0;

  // make sure we're called back with a result structure for a parent
  // that is being retried.
  if (status == PL_NH_MARK_UP) {
    ink_assert(state->retry == true);
  }
  if (state->result != PL_NH_PARENT_SPECIFIED) {
    return;
  }

  const std::string host_port = PLHostRecord::makeHostPort(std::string_view(hostname, hostname_len), port);
  auto iter                   = host_map.find(host_port);
  if (iter == host_map.end()) {
    PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRId64 "] no host named %s found in host_map", sm_id, host_port.c_str());
    return;
  }

  std::shared_ptr h = iter->second;

  switch (status) {
  // Mark the host up.
  case PL_NH_MARK_UP:
    if (!h->available) {
      h->set_available();
      PL_NH_Note("[%" PRId64 "] http parent proxy %s restored", sm_id, hostname);
    }
    break;
  // Mark the host down.
  case PL_NH_MARK_DOWN:
    if (h->failedAt == 0 || state->retry == true) {
      { // lock guard
        std::lock_guard<std::mutex> guard(h->_mutex);
        if (h->failedAt == 0) {
          h->failedAt = _now;
          if (state->retry == false) {
            new_fail_count = h->failCount = 1;
          }
        } else if (state->retry == true) {
          h->failedAt = _now;
        }
      } // end lock guard
      PL_NH_Note("[%" PRId64 "] NextHop %s marked as down %s", sm_id, (state->retry) ? "retry" : "initially", h->hostname.c_str());
    } else {
      int old_count = 0;
      // if the last failure was outside the retry window, set the failcount to 1 and failedAt to now.
      { // lock guard
        std::lock_guard<std::mutex> lock(h->_mutex);
        if ((h->failedAt + retry_time) < static_cast<unsigned>(_now)) {
          h->failCount = 1;
          h->failedAt  = _now;
        } else {
          old_count = h->failCount = 1;
        }
        new_fail_count = old_count + 1;
      } // end of lock_guard
      PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRId64 "] Parent fail count increased to %d for %s", sm_id, new_fail_count,
                  h->hostname.c_str());
    }

    if (new_fail_count >= fail_threshold) {
      h->set_unavailable();
      PL_NH_Note("[%" PRId64 "] Failure threshold met failcount:%d >= threshold:%" PRId64 ", http parent proxy %s marked down",
                 sm_id, new_fail_count, fail_threshold, h->hostname.c_str());
      PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRId64 "] NextHop %s marked unavailable, h->available=%s", sm_id, h->hostname.c_str(),
                  (h->available) ? "true" : "false");
    }
    break;
  }
}
