/*
 * 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 "ClientRPCHook.h"
#include "CommandHeader.h"
#include "Logging.h"
extern "C" {
#include "spas_client.h"
}
#include "string"

namespace rocketmq {

const string SessionCredentials::AccessKey = "AccessKey";
const string SessionCredentials::SecretKey = "SecretKey";
const string SessionCredentials::Signature = "Signature";
const string SessionCredentials::SignatureMethod = "SignatureMethod";
const string SessionCredentials::ONSChannelKey = "OnsChannel";

void ClientRPCHook::doBeforeRequest(const string& remoteAddr, RemotingCommand& request) {
  CommandHeader* header = request.getCommandHeader();

  map<string, string> requestMap;
  string totalMsg;

  requestMap.insert(pair<string, string>(SessionCredentials::AccessKey, sessionCredentials.getAccessKey()));
  requestMap.insert(pair<string, string>(SessionCredentials::ONSChannelKey, sessionCredentials.getAuthChannel()));

  LOG_DEBUG("before insert declared filed,MAP SIZE is:" SIZET_FMT "", requestMap.size());
  if (header != NULL) {
    header->SetDeclaredFieldOfCommandHeader(requestMap);
  }
  LOG_DEBUG("after insert declared filed, MAP SIZE is:" SIZET_FMT "", requestMap.size());

  map<string, string>::iterator it = requestMap.begin();
  for (; it != requestMap.end(); ++it) {
    totalMsg.append(it->second);
  }
  const MemoryBlock* pBody = request.GetBody();
  if (pBody && pBody->getSize() > 0) {
    const char* msg_body = const_cast<const char*>(static_cast<char*>(pBody->getData()));
    LOG_DEBUG("msgBody is:%s, msgBody length is:%d", msg_body, pBody->getSize());
    totalMsg.append(msg_body, pBody->getSize());
  } else if (request.getMsgBody().length() > 0) {
    LOG_DEBUG("msgBody is:%s, msgBody length is:" SIZET_FMT "", request.getMsgBody().c_str(),
              request.getMsgBody().length());
    totalMsg.append(request.getMsgBody());
  }
  LOG_DEBUG("total msg info are:%s, size is:" SIZET_FMT "", totalMsg.c_str(), totalMsg.size());
  char* pSignature =
      rocketmqSignature::spas_sign(totalMsg.c_str(), totalMsg.size(), sessionCredentials.getSecretKey().c_str());
  // char *pSignature = spas_sign(totalMsg.c_str(),
  // sessionCredentials.getSecretKey().c_str());

  if (pSignature != NULL) {
    string signature(static_cast<const char*>(pSignature));
    request.addExtField(SessionCredentials::Signature, signature);
    request.addExtField(SessionCredentials::AccessKey, sessionCredentials.getAccessKey());
    request.addExtField(SessionCredentials::ONSChannelKey, sessionCredentials.getAuthChannel());
    rocketmqSignature::spas_mem_free(pSignature);
  } else {
    LOG_ERROR("signature for request failed");
  }
}
}  // namespace rocketmq
