/*******************************************************************************
 * Copyright (c) 2017-2018 Marc Jakobi, github.com/MrcJkb, fortiss GmbH
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *    Marc Jakobi - initial implementation for HTTP clients
 *    Jose Cabral - Merge old HTTPIpLayer to this one and use CIEC_STRING
 ********************************************************************************/

#include "httplayer.h"
#include "httpparser.h"
#include "../../arch/devlog.h"
#include <string.h>
#include "basecommfb.h"
#include "http_handler.h"
#include "comtypes.h"

using namespace forte::com_infra;

CHttpComLayer::CHttpComLayer(CComLayer* paUpperLayer, CBaseCommFB* paComFB) :
    CComLayer(paUpperLayer, paComFB), mInterruptResp(e_Nothing), mRequestType(e_NOTSET), mPort(80), mBufFillSize(0), mCorrectlyInitialized(false),
        mHasParameterInSD(false) {
  memset(mRecvBuffer, 0, sizeof(mRecvBuffer));
}

CHttpComLayer::~CHttpComLayer() {
  closeConnection();
}

EComResponse CHttpComLayer::openConnection(char *paLayerParameter) {
  EComResponse eRetVal = e_InitInvalidId;

  if(checkSDsAndRDsType()) {
    switch(m_poFb->getComServiceType()){
      case e_Server:
        if(1 == m_poFb->getNumSD()) {
          mPath = paLayerParameter;
          if(getExtEvHandler<CHTTP_Handler>().addServerPath(this, mPath)) {
            eRetVal = e_InitOk;
          }
        } else {
          DEVLOG_ERROR("[HTTP Layer] The FB with PARAM %s coudln't be initialized since only one SD is possible in HTTP Server which is for the response\n",
            paLayerParameter);
        }
        break;
      case e_Client:
        eRetVal = openClientConnection(paLayerParameter);
        break;
      default:
        // e_Publisher and e_Subscriber
        eRetVal = e_ProcessDataInvalidObject;
        break;
    }
  }

  mCorrectlyInitialized = (eRetVal == e_InitOk);
  return eRetVal;
}

EComResponse CHttpComLayer::openClientConnection(char* paLayerParameter) {
  EComResponse eRetVal = e_InitInvalidId;
  unsigned int numberOfSD = m_poFb->getNumSD();

  if(2 == m_poFb->getNumRD()) {
    CParameterParser parser(paLayerParameter, ';', 3); //IP:PORT;POST|PUT|GET;[content-type]

    if(handleContentAndRequestType(parser, parser.parseParameters()) && handleAddress(parser[0], numberOfSD)) {

      switch(mRequestType){
        case e_PUT:
        case e_POST:
          if(checkSDInPOSTAndPUT(numberOfSD)) {
            CHttpParser::createPutPostRequest(mRequest, mHost, mPath, mReqData, mContentType, mRequestType);
            eRetVal = e_InitOk;
            DEVLOG_INFO("[HTTP Layer] FB with PUT/POST request initialized. Host: %s, Path: %s\n", mHost.getValue(), mPath.getValue());
          }
          break;
        case e_GET:
          if(0 != numberOfSD) {
            DEVLOG_WARNING("[HTTP Layer] FB with GET request has SD which are ignore. If you want to have parameters, put them in the path in the PARAMS\n");
          }
          CHttpParser::createGetRequest(mRequest, mHost, mPath);
          eRetVal = e_InitOk;
          DEVLOG_INFO("[HTTP Layer] FB with GET request initialized. Host: %s, Path: %s\n", mHost.getValue(), mPath.getValue());
          break;
        default:
          break;
      }
    }
  } else {
    DEVLOG_ERROR(
      "[HTTP Layer] A client should ALWAYS have exactly 2 RD, the first one for the response code, and the second for the response body, even for PUT and POST\n");
  }

  m_eConnectionState = e_Disconnected;
  return eRetVal;
}

bool CHttpComLayer::checkSDInPOSTAndPUT(size_t paNoOfSD) {
  bool evetythingOK = true;

  if(0 == paNoOfSD) {
    if("" == mReqData) {
      DEVLOG_ERROR("[HTTP Layer] You are using a POST/PUT FB but no data is defined as SD nor as parameters in PARAMS\n");
      evetythingOK = false;
    }
  } else if(1 == paNoOfSD) {
    if("" != mReqData) {
      DEVLOG_WARNING("[HTTP Layer] Parameters in PARAMS are ignored for PUT/POST request data and SDs are sent instead\n");
    }
    mHasParameterInSD = true;
  } else {
    DEVLOG_ERROR("[HTTP Layer] You can use maximum 1 SD\n");
    evetythingOK = false;
  }

  return evetythingOK;
}

bool CHttpComLayer::checkSDsAndRDsType() {

  for(size_t i = 2; i < m_poFb->getNumSD(); i++) {
    CIEC_ANY::EDataTypeID typeToCheck = m_poFb->getDI(static_cast<unsigned int>(i))->getDataTypeID();
    if(CIEC_ANY::e_ANY != typeToCheck && CIEC_ANY::e_STRING != typeToCheck && CIEC_ANY::e_WSTRING != typeToCheck) {
      DEVLOG_ERROR("[HTTP Layer] Client called %s has an invalid SD_%d\n", CStringDictionary::getInstance().get(m_poFb->getInstanceNameId()), i);
      return false;
    }
  }

  for(size_t i = 2; i < m_poFb->getNumRD(); i++) {
    CIEC_ANY::EDataTypeID typeToCheck = m_poFb->getDO(static_cast<unsigned int>(i))->getDataTypeID();
    if(CIEC_ANY::e_ANY != typeToCheck && CIEC_ANY::e_STRING != typeToCheck && CIEC_ANY::e_WSTRING != typeToCheck) {
      DEVLOG_ERROR("[HTTP Layer] Client called %s has an invalid RD_%d\n", CStringDictionary::getInstance().get(m_poFb->getInstanceNameId()), i);
      return false;
    }
  }
  return true;
}

bool CHttpComLayer::storeRequestType(const char* paType) {
  bool everythingOK = true;
  if(0 == strcmp(paType, "POST")) {
    mRequestType = e_POST;
  } else if(0 == strcmp(paType, "PUT")) {
    mRequestType = e_PUT;
  } else if(0 == strcmp(paType, "GET")) {
    mRequestType = e_GET;
  } else {
    DEVLOG_ERROR("[HTTP Layer] GET, PUT or POST must be defined, but %s was defined instead\n", paType);
    everythingOK = false;
  }
  return everythingOK;
}

bool CHttpComLayer::handleContentAndRequestType(CParameterParser &paParser, size_t paNoOfParameters) {
  bool everythingOK = true;
  if(1 < paNoOfParameters) {
    if(3 == paNoOfParameters) {
      mContentType = paParser[2];
    } else {
      mContentType = "text/html";
    }
    everythingOK = storeRequestType(paParser[1]);
  } else {
    everythingOK = false;
    DEVLOG_ERROR("[HTTP Layer] Wrong parameters. It should be as IP:PORT;POST|PUT|GET;[content-type]\n");
  }
  return everythingOK;
}

bool CHttpComLayer::handleAddress(const char* paAddress, size_t paNoOfSDs) {
  bool everythingOK = true;

  //look for parameters
  CParameterParser parser(paAddress, '?', 2); //IP:PORT/PATH?PARAMETERS
  CIEC_STRING addressToParse = paAddress;
  if(2 == parser.parseParameters() && (e_PUT == mRequestType || e_POST == mRequestType)) {
    if(0 == paNoOfSDs) { //if SDs are present, the parameters in PARAMS are ignored
      mReqData = parser[1];
      mContentType = "application/x-www-form-urlencoded";
    }
    addressToParse = parser[0];
  }

  char* firstSlash = strchr(addressToParse.getValue(), '/');

  if(firstSlash) {
    mPath = firstSlash;
    *firstSlash = '\0';
    CParameterParser portParser(addressToParse.getValue(), ':', 2);
    if(2 == portParser.parseParameters()) {
      mHost = portParser[0];
      mPort = static_cast<TForteUInt16>(forte::core::util::strtoul(portParser[1], 0, 10));
    } else {
      mHost = addressToParse.getValue();
      DEVLOG_INFO("[HTTP Layer] No port was found on the parameter, using default 80\n");
    }
  } else {
    everythingOK = false;
    DEVLOG_ERROR("[HTTP Layer] No path was found on the parameter\n");
  }
  return everythingOK;
}

EComResponse CHttpComLayer::sendData(void *paData, unsigned int) {
  mInterruptResp = e_Nothing;
  if(mCorrectlyInitialized) {
    switch(m_poFb->getComServiceType()){
      case e_Server:
        sendDataAsServer(paData);
        break;
      case e_Client:
        sendDataAsClient(paData);
        break;
      default:
        // e_Publisher and e_Subscriber
        break;
    }
  } else {
    DEVLOG_ERROR("[HTTP Layer]The FB is not initialized\n");
  }

  return mInterruptResp;
}

void CHttpComLayer::sendDataAsServer(const void *paData) {
  bool error = false;
  TConstIEC_ANYPtr apoSDs = static_cast<TConstIEC_ANYPtr>(paData);
  if(!serializeData(apoSDs[0])) {
    error = true;
  } else {
    CHttpParser::createResponse(mRequest, "HTTP/1.1 200 OK", mContentType, mReqData);
  }
  if(error) {
    getExtEvHandler<CHTTP_Handler>().forceClose(this);
    mInterruptResp = e_ProcessDataDataTypeError;
  } else {
    getExtEvHandler<CHTTP_Handler>().sendServerAnswer(this, mRequest);
    mInterruptResp = e_ProcessDataOk;
  }
}

void CHttpComLayer::sendDataAsClient(const void *paData) {
  bool error = false;
  if(mHasParameterInSD) {
    TConstIEC_ANYPtr apoSDs = static_cast<TConstIEC_ANYPtr>(paData);
    if(!serializeData(apoSDs[0])) {
      error = true;
      DEVLOG_ERROR("[HTTP Layer] Error in data serialization\n");
    } else {
      if(!CHttpParser::changePutPostData(mRequest, mReqData)) {
        DEVLOG_ERROR("[HTTP Layer] Wrong PUT/POST request when changing the data\n");
        error = true;
      }
    }
  }

  if(!error) {
    if(getExtEvHandler<CHTTP_Handler>().sendClientData(this, mRequest)) {
      mInterruptResp = e_ProcessDataOk;
    } else {
      mInterruptResp = e_ProcessDataSendFailed;
      DEVLOG_ERROR("[HTTP Layer] Sending request on TCP failed\n");
    }
  } else {
    mInterruptResp = e_ProcessDataDataTypeError;
  }
}

EComResponse CHttpComLayer::recvData(const void *paData, unsigned int paSize) {
  mInterruptResp = e_Nothing;
  if(mCorrectlyInitialized) {
    memcpy(mRecvBuffer, paData, (paSize > cg_unIPLayerRecvBufferSize) ? cg_unIPLayerRecvBufferSize : paSize);
    switch(m_poFb->getComServiceType()){
      case e_Server:
        DEVLOG_ERROR("[HTTP Layer] Receiving raw data as a Server? That's wrong, use the recvServerData function\n");
        break;
      case e_Client:
        if(0 == paData) { //timeout occurred
          mInterruptResp = e_ProcessDataRecvFaild;
        } else {
          if(e_ProcessDataOk != (mInterruptResp = handleHTTPResponse(mRecvBuffer))) {
            DEVLOG_ERROR("[HTTP Layer] FB with host: %s:%u couldn't handle the HTTP response\n", mHost.getValue(), mPort);
          } else {
            //TODO Trigger event?
          }
        }
        break;
      default:
        break;
    }
  } else {
    DEVLOG_ERROR("[HTTP Layer]The FB is not initialized\n");
  }
  if(e_ProcessDataOk == mInterruptResp) {
    m_poFb->interruptCommFB(this);
  }
  return mInterruptResp;
}

EComResponse forte::com_infra::CHttpComLayer::recvServerData(CSinglyLinkedList<CIEC_STRING>&, CSinglyLinkedList<CIEC_STRING>& paParameterValues) {
  //for now, the parameterNames are not taken in account, and the parameters are put in the same order they arrived

  mInterruptResp = e_Nothing;
  bool failed = false;
  if(0 < m_poFb->getNumSD()) {
    unsigned int noOfParameters = 0;
    for(CSinglyLinkedList<CIEC_STRING>::Iterator iter = paParameterValues.begin(); iter != paParameterValues.end(); ++iter) {
      noOfParameters++;
    }

    if(noOfParameters == m_poFb->getNumRD()) {
      noOfParameters = 0;
      for(CSinglyLinkedList<CIEC_STRING>::Iterator iter = paParameterValues.begin(); iter != paParameterValues.end(); ++iter) {
        m_poFb->getRDs()[noOfParameters++].setValue(*iter);
      }
    } else {
      DEVLOG_ERROR("[HTTP Layer] FB with path %s received a number of parameters of %u, while it has %u SDs\n", mPath.getValue(),
        static_cast<TForteUInt16>(noOfParameters), m_poFb->getNumRD());
      failed = true;
    }
  }

  if(failed) {
    CIEC_STRING toSend;
    CIEC_STRING result = "HTTP/1.1 400 Bad Request";
    mReqData = "";
    CHttpParser::createResponse(toSend, result, mContentType, mReqData);
    getExtEvHandler<CHTTP_Handler>().sendServerAnswerFromRecv(this, toSend);
    mInterruptResp = e_ProcessDataDataTypeError;
  } else {
    mInterruptResp = e_ProcessDataOk;
  }
  if(e_ProcessDataOk == mInterruptResp) {
    m_poFb->interruptCommFB(this);
  }
  return mInterruptResp;
}

EComResponse CHttpComLayer::handleHTTPResponse(char *paData) {
  DEVLOG_DEBUG("[HTTP Layer] Handling received HTTP response\n");
  EComResponse eRetVal = e_ProcessDataRecvFaild;
  if(m_poFb != 0) {
    CIEC_ANY* apoRDs = m_poFb->getRDs();
    // Interpret HTTP response and set output status according to success/failure.
    CIEC_STRING responseCode;
    CIEC_STRING output;
    CHttpParser::parseResponse(output, responseCode, paData) ? eRetVal = e_ProcessDataOk : eRetVal = e_ProcessDataRecvFaild;
    apoRDs[0].fromString(responseCode.getValue());
    apoRDs[1].fromString(output.getValue());
  } else {
    DEVLOG_ERROR("[HTTP Layer] No FB defined\n");
  }
  return eRetVal;
}

EComResponse CHttpComLayer::processInterrupt() {
  mInterruptResp = e_ProcessDataOk;
  return mInterruptResp;
}

void CHttpComLayer::closeConnection() {
  if(e_Server == m_poFb->getComServiceType()) {
    getExtEvHandler<CHTTP_Handler>().removeServerPath(mPath);
  }
  getExtEvHandler<CHTTP_Handler>().forceClose(this);
}

bool CHttpComLayer::serializeData(const CIEC_ANY& paCIECData) {
  size_t bufferSize = paCIECData.getToStringBufferSize();
  char acDataValue[bufferSize];
  int nConsumedBytes;
  switch(paCIECData.getDataTypeID()){
    case CIEC_ANY::e_WSTRING:
      nConsumedBytes = static_cast<const CIEC_WSTRING&>(paCIECData).toUTF8(acDataValue, bufferSize, false);
      break;
    case CIEC_ANY::e_STRING:
      nConsumedBytes = static_cast<const CIEC_STRING&>(paCIECData).toUTF8(acDataValue, bufferSize, false);
      break;
    default:
      nConsumedBytes = paCIECData.toString(acDataValue, bufferSize);
      break;
  }
  if(-1 != nConsumedBytes) {
    acDataValue[nConsumedBytes] = '\0';
  }
  mReqData = acDataValue;
  return true;
}

CIEC_STRING& forte::com_infra::CHttpComLayer::getHost() {
  return mHost;
}

TForteUInt16 forte::com_infra::CHttpComLayer::getPort() {
  return mPort;
}

