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

#include <algorithm>
#include <chrono>
#include <string>
#include <memory>
#include <utility>
#include <map>
#include <thread>

#include "io/BaseStream.h"
#include "TestBase.h"
#include "unit/SiteToSiteHelper.h"
#include "sitetosite/CPeer.h"
#include "sitetosite/CRawSocketProtocol.h"
#include "sitetosite/CSiteToSite.h"
#include "sitetosite/RawSocketProtocol.h"
#include "core/cstructs.h"
#include "RandomServerSocket.h"
#include "core/log.h"

#define FMT_DEFAULT fmt_lower

const char * ATTR_NAME = "some_key";
const char * ATTR_VALUE = "some value";
const char * PAYLOAD = "Test MiNiFi payload";
const char * PAYLOAD_CRC = "2006463717"; // Depends on both payload and attributes, do NOT change manually!
std::string CODEC_NAME = "StandardFlowFileCodec";

struct S2SReceivedData {
  bool request_type_ok = false;
  std::string magic_string;
  uint32_t attr_num = 0;
  std::map<std::string, std::string> attributes;
  std::vector<uint8_t> payload;
};

// This struct is used to sync between simulated clients and servers
struct TransferState {
  std::atomic<bool> handshake_data_processed{false};
  std::atomic<bool> transer_completed{false};
  std::atomic<bool> data_processed{false};

};

void wait_until(std::atomic<bool>& b) {
  while(!b) {
    std::this_thread::sleep_for(std::chrono::milliseconds(0)); //Just yield
  }
}

TEST_CASE("TestSetPortId", "[S2S1]") {
  SiteToSiteCPeer peer;
  initPeer(&peer, "fake_host", 65433, "");
  CRawSiteToSiteClient * protocol = (CRawSiteToSiteClient*)malloc(sizeof(CRawSiteToSiteClient));

  initRawClient(protocol, &peer);

  std::string uuid_str = "c56a4180-65aa-42ec-a945-5fd21dec0538";

  setPortId(protocol, uuid_str.c_str());

  REQUIRE(uuid_str == std::string(getPortId(protocol)));

  tearDown(protocol);

  freePeer(&peer);

  free(protocol);
}

void send_response_code(minifi::io::BaseStream* stream, uint8_t resp) {
  std::array<uint8_t, 3> resp_codes = {'R', 'C', resp};
  for(uint8_t r : resp_codes) {
    stream->write(&r, 1);
  }
}

void accept_transfer(minifi::io::BaseStream* stream, const std::string& crcstr, TransferState& transfer_state, S2SReceivedData& s2s_data) {
  //In long term it would be nice to calculate the crc of the received data here
  send_response_code(stream, 12); // confirmed
  stream->writeUTF(crcstr);
  send_response_code(stream, 13); // transaction finished

  wait_until(transfer_state.transer_completed);

  std::string requesttype;
  stream->readUTF(requesttype);

  if(requesttype == "SEND_FLOWFILES") {
    s2s_data.request_type_ok = true;
    stream->read(s2s_data.attr_num);
    std::string key, value;
    for(int i = 0; i < s2s_data.attr_num; ++i) {
      stream->readUTF(key, true);
      stream->readUTF(value, true);
      s2s_data.attributes[key] = value;
    }
    uint64_t content_size=0;
    stream->read(content_size);
    s2s_data.payload.resize(content_size);
    stream->readData(s2s_data.payload, content_size);
  } else {
    s2s_data.request_type_ok = false;
  }
  transfer_state.data_processed = true;
}

void sunny_path_bootstrap(minifi::io::BaseStream* stream, TransferState& transfer_state, S2SReceivedData& s2s_data) {
  //Verify the magic string
  char c_array[4];
  stream->readData((uint8_t*)c_array, 4);
  s2s_data.magic_string = std::string(c_array, 4);
  uint8_t success = 0x14;
  stream->write(&success, 1);
  send_response_code(stream, 0x1);
  stream->write(&success, 1);

  //just consume handshake data
  bool found_codec = false;
  int read_len = 0;
  while(!found_codec) {
    uint8_t handshake_data[1000];
    int actual_len = stream->readData(handshake_data+read_len, 1000-read_len);
    if(actual_len <= 0) {
      continue;
    }
    read_len += actual_len;
    std::string incoming_data(reinterpret_cast<const char *>(handshake_data), read_len);
    auto it = std::search(incoming_data.begin(), incoming_data.end(), CODEC_NAME.begin(), CODEC_NAME.end());
    if(it != incoming_data.end()){
      size_t idx = std::distance(incoming_data.begin(), it);
      //Actual version follows the string as an uint32_t // that should be the end of the buffer
      found_codec = idx + CODEC_NAME.length() + sizeof(uint32_t) == read_len;
    }
  }

  transfer_state.handshake_data_processed = true;
}

void different_version_bootstrap(minifi::io::BaseStream* stream, TransferState& transfer_state, S2SReceivedData& s2s_data) {
  uint8_t resp_code = 0x15;
  stream->write(&resp_code, 1);

  uint32_t version = 4;
  stream->write(version);

  sunny_path_bootstrap(stream, transfer_state, s2s_data);
}

TEST_CASE("TestSiteToBootStrap", "[S2S3]") {

  std::array<std::function<void(minifi::io::BaseStream*, TransferState&, S2SReceivedData&)>, 2> bootstrap_functions =
      {sunny_path_bootstrap, different_version_bootstrap};

  for(const auto& bootstrap_func : bootstrap_functions) {
    TransferState transfer_state;
    S2SReceivedData received_data;
    std::unique_ptr<minifi::io::ServerSocket> sckt(new minifi::io::RandomServerSocket("localhost"));
    uint16_t port = sckt->getPort();

    sckt->registerCallback([]() -> bool { return true; },  [&bootstrap_func, &transfer_state, &received_data](minifi::io::BaseStream* stream)
      {bootstrap_func(stream, transfer_state, received_data); accept_transfer(stream, PAYLOAD_CRC, transfer_state, received_data); } );

    bool c_handshake_ok = false;
    bool c_transfer_ok = false;

    auto c_client_thread = [&transfer_state, &c_handshake_ok, &c_transfer_ok, port]() {
      SiteToSiteCPeer cpeer;
      initPeer(&cpeer, "localhost", port, "");

      CRawSiteToSiteClient cprotocol;

      initRawClient(&cprotocol, &cpeer);

      std::string uuid_str = "C56A4180-65AA-42EC-A945-5FD21DEC0538";

      c_handshake_ok = bootstrap(&cprotocol) == 0;

      const char * payload = PAYLOAD;

      attribute attribute1;

      attribute1.key = ATTR_NAME;
      const char * attr_value = ATTR_VALUE;
      attribute1.value = (void *)attr_value;
      attribute1.value_size = strlen(attr_value);

      attribute_set as;
      as.size = 1;
      as.attributes = &attribute1;

      wait_until(transfer_state.handshake_data_processed);
      c_transfer_ok = (transmitPayload(&cprotocol, payload, &as) == 0);
      transfer_state.transer_completed = true;

      destroyClient(&cprotocol);
    };

    std::thread c_thread(c_client_thread);
    c_thread.join();
    wait_until(transfer_state.data_processed);

    REQUIRE(c_handshake_ok == true);
    REQUIRE(c_transfer_ok == true);

    REQUIRE(received_data.magic_string == "NiFi");
    REQUIRE(received_data.request_type_ok);
    REQUIRE(received_data.attr_num == 1);
    REQUIRE(received_data.attributes[ATTR_NAME] == ATTR_VALUE);
    REQUIRE(std::string(reinterpret_cast<const char*>(received_data.payload.data()), received_data.payload.size()) == PAYLOAD);
  }
}
