/*******************************************************************************
 * Copyright (c) 2018 - 2019 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:
 *    Jose Cabral, Kirill Dorofeev - initial implementation
 *******************************************************************************/

#include "opcua_remote_handler.h"
#include "../../core/devexec.h"
#include "../../core/iec61131_functions.h"
#include "../../core/cominfra/basecommfb.h"
#include <criticalregion.h>
#include <forte_printer.h>

using namespace forte::com_infra;

DEFINE_HANDLER(COPC_UA_Remote_Handler);

COPC_UA_Client_IterationList::COPC_UA_Client_IterationList() :
    mNewClientsPresent(false) {
}

COPC_UA_Client_IterationList::~COPC_UA_Client_IterationList() {
}

void COPC_UA_Client_IterationList::startIterationThread() {
  if(!isAlive()) {
    start();
    mClientsThreadStarted.waitIndefinitely();
  }
}

void COPC_UA_Client_IterationList::stopIterationThread() {
  setAlive(false);
  resumeIterationLoop();
  end();
}

void COPC_UA_Client_IterationList::addClient(CUA_ClientInformation& paClientInformation) {
  if(paClientInformation.isClientValid()) {
    CCriticalRegion iterationListRegion(mNewClientsMutex);
    addClientToList(paClientInformation, mNewClients);
    mNeedsIteration.inc();
    mNewClientsPresent = true;
  }
}

void COPC_UA_Client_IterationList::removeClient(CUA_ClientInformation& paClientInformation) {
  CCriticalRegion iterationListRegion(mIterationClientsMutex);
  CCriticalRegion newClientsRegion(mNewClientsMutex);
  mNewClients.erase(&paClientInformation); //client could still be in the newList
  mIterationClients.erase(&paClientInformation);
}

void COPC_UA_Client_IterationList::run() {
  mClientsThreadStarted.inc();
  while(isAlive()) {

    if(mNewClientsPresent) {
      updateClientList();
    }
    bool needsRetry = handleClients();
    if(isAlive()) {
      if(needsRetry) {
        mNeedsIteration.timedWait(scmNanosecondsToSleep);
      } else {
        mNeedsIteration.waitIndefinitely();
      }
    }
  }
}

void COPC_UA_Client_IterationList::resumeIterationLoop() {
  mNeedsIteration.inc();
}

void COPC_UA_Client_IterationList::addClientToList(CUA_ClientInformation& paClientInformation, CSinglyLinkedList<CUA_ClientInformation*>& paList) {
  bool elementAlreadyPresent = false;
  for(CSinglyLinkedList<CUA_ClientInformation *>::Iterator itClientInformation = paList.begin(); itClientInformation != paList.end(); ++itClientInformation) {
    if(&paClientInformation == (*itClientInformation)) {
      elementAlreadyPresent = true;
      break;
    }
  }

  if(!elementAlreadyPresent) {
    paList.pushBack(&paClientInformation);
  }
}

void COPC_UA_Client_IterationList::updateClientList() {
  CCriticalRegion iterationListRegion(mIterationClientsMutex);
  CCriticalRegion newClientsRegion(mNewClientsMutex);
  for(CSinglyLinkedList<CUA_ClientInformation *>::Iterator itClientInformation = mNewClients.begin(); itClientInformation != mNewClients.end();
      ++itClientInformation) {
    addClientToList(**itClientInformation, mIterationClients);
  }
  mNewClients.clearAll();
  mNewClientsPresent = false;
}

// ***************** CLIENT HANDLER ************* //

COPC_UA_Remote_Handler::COPC_UA_Remote_Handler(CDeviceExecution& paDeviceExecution) :
    COPC_UA_HandlerAbstract(paDeviceExecution), mConnectionHandler(*this) {
}

COPC_UA_Remote_Handler::~COPC_UA_Remote_Handler() {
  disableHandler();
  cleanResources();
}

void COPC_UA_Remote_Handler::enableHandler(void) {
  startIterationThread();
  mConnectionHandler.startIterationThread();
}

void COPC_UA_Remote_Handler::disableHandler(void) {
  mConnectionHandler.stopIterationThread();
  stopIterationThread();
}

UA_StatusCode COPC_UA_Remote_Handler::initializeAction(CActionInfo& paActionInfo) {
  enableHandler();
  UA_StatusCode retVal = UA_STATUSCODE_BADINTERNALERROR;
  switch(paActionInfo.getAction()){
    case CActionInfo::eRead:
    case CActionInfo::eWrite:
    case CActionInfo::eCallMethod:
    case CActionInfo::eSubscribe:
      retVal = getClientAndAddAction(paActionInfo);
      break;
    case CActionInfo::eCreateMethod:
    case CActionInfo::eCreateObject:
    case CActionInfo::eDeleteObject:
      DEVLOG_ERROR("[OPC UA REMOTE]: Cannot perform action %s remotely. Initialization failed\n", CActionInfo::mActionNames[paActionInfo.getAction()]);
      break;
    default:
      DEVLOG_ERROR("[OPC UA REMOTE]: Unknown action %d to be initialized\n", paActionInfo.getAction());
      break;
  }
  return retVal;
}

UA_StatusCode COPC_UA_Remote_Handler::executeAction(CActionInfo& paActionInfo) {

  CUA_ClientInformation *clientInfo = getClient(paActionInfo.getEndpoint());
  UA_StatusCode retVal = UA_STATUSCODE_BADINTERNALERROR;

  if(clientInfo && clientInfo->isActionInitialized(paActionInfo)) {
    switch(paActionInfo.getAction()){
      case CActionInfo::eRead:
        retVal = clientInfo->executeRead(paActionInfo);
        break;
      case CActionInfo::eWrite:
        retVal = clientInfo->executeWrite(paActionInfo);
        break;
      case CActionInfo::eCallMethod:
        retVal = clientInfo->executeCallMethod(paActionInfo);
        break;
      default: //eCreateMethod, eCreateObject, eDeleteObject will never reach here since they weren't initialized. eSubscribe is a Subscribe FB
        DEVLOG_ERROR("[OPC UA REMOTE]: Action %d to be executed is unknown or invalid\n", paActionInfo.getAction());
        break;
    }
  } else {
    DEVLOG_ERROR("[OPC UA REMOTE]: Cannot execute action from FB %s. It was not properly initialized\n",
      paActionInfo.getLayer().getCommFB()->getInstanceName());
  }

  if(UA_STATUSCODE_GOOD == retVal) {
    resumeIterationLoop();
  }

  return retVal;
}

UA_StatusCode COPC_UA_Remote_Handler::uninitializeAction(CActionInfo& paActionInfo) {
  UA_StatusCode retVal = UA_STATUSCODE_BADINTERNALERROR;
  switch(paActionInfo.getAction()){
    case CActionInfo::eRead:
    case CActionInfo::eWrite:
    case CActionInfo::eCallMethod:
    case CActionInfo::eSubscribe:
      removeActionFromClient(paActionInfo);
      retVal = UA_STATUSCODE_GOOD;
      break;
    default:
      DEVLOG_ERROR("[OPC UA REMOTE]: Action %d to be uninitialized is unknown or invalid\n", paActionInfo.getAction());
      break;
  }
  return retVal;
}

void COPC_UA_Remote_Handler::cleanResources() {
  CCriticalRegion criticalRegion(mAllClientListMutex);
  for(CSinglyLinkedList<CUA_ClientInformation*>::Iterator itClientInformation = mAllClients.begin(); itClientInformation != mAllClients.end();
      ++itClientInformation) {
    mConnectionHandler.removeClient(**itClientInformation);
    removeClient(**itClientInformation);
    delete *itClientInformation;
  }
  mAllClients.clearAll();
}

UA_StatusCode COPC_UA_Remote_Handler::getClientAndAddAction(CActionInfo& paActionInfo) {
  UA_StatusCode retVal = UA_STATUSCODE_BADINTERNALERROR;
  CUA_ClientInformation *clientInfo = getClient(paActionInfo.getEndpoint());
  if(clientInfo) {
    addActionToClient(paActionInfo);
    retVal = UA_STATUSCODE_GOOD;
  }
  return retVal;
}

CUA_ClientInformation* COPC_UA_Remote_Handler::getClient(const CIEC_STRING &paEndpoint) {
  CCriticalRegion allClientsRegion(mAllClientListMutex);

  CUA_ClientInformation *client = 0;
  for(CSinglyLinkedList<CUA_ClientInformation *>::Iterator itClientInformation = mAllClients.begin(); itClientInformation != mAllClients.end();
      ++itClientInformation) {
    if((*itClientInformation)->getEndpoint() == paEndpoint) {
      client = (*itClientInformation);
      break;
    }
  }
  if(!client) {
    client = new CUA_ClientInformation(paEndpoint);
    if(client->configureClient()) {
      mAllClients.pushBack(client);
    } else {
      delete client;
      client = 0;
    }
  }

  return client;
}

void COPC_UA_Remote_Handler::addActionToClient(CActionInfo& paActionInfo) {
  CCriticalRegion allClientsRegion(mAllClientListMutex);
  for(CSinglyLinkedList<CUA_ClientInformation *>::Iterator itClientInformation = mAllClients.begin(); itClientInformation != mAllClients.end();
      ++itClientInformation) {
    CCriticalRegion clientRegion((*itClientInformation)->getMutex());
    if((*itClientInformation)->getEndpoint() == paActionInfo.getEndpoint()) {
      (*itClientInformation)->addAction(paActionInfo);
      addClientToConnectionHandler(**itClientInformation);
      break;
    }
  }
}

void COPC_UA_Remote_Handler::removeActionFromClient(CActionInfo& paActionInfo) {
  CCriticalRegion allClientsRegion(mAllClientListMutex);

  CUA_ClientInformation *clientToDelete = 0;
  for(CSinglyLinkedList<CUA_ClientInformation *>::Iterator itClientInformation = mAllClients.begin(); itClientInformation != mAllClients.end();
      ++itClientInformation) {
    CCriticalRegion clientRegion((*itClientInformation)->getMutex());
    if((*itClientInformation)->getEndpoint() == paActionInfo.getEndpoint()) {
      (*itClientInformation)->removeAction(paActionInfo);
      clientToDelete = *itClientInformation;
      break;
    }
  }

  if(clientToDelete && !clientToDelete->hasActions()) {
    removeClientFromAllLists(*clientToDelete);
  }
}

void COPC_UA_Remote_Handler::removeClientFromAllLists(CUA_ClientInformation& paClientInformation) {
  paClientInformation.setClientToInvalid();
  mConnectionHandler.removeClient(paClientInformation);
  removeClient(paClientInformation);
  mAllClients.erase(&paClientInformation);
  delete &paClientInformation;
}

void COPC_UA_Remote_Handler::addClientToConnectionHandler(CUA_ClientInformation& paClientInformation) {
  mConnectionHandler.addClient(paClientInformation);
}

bool COPC_UA_Remote_Handler::handleClients() {
  CCriticalRegion iterationCriticalRegion(mIterationClientsMutex); //this is needed because removing a client from the list could cause trouble
  CSinglyLinkedList<CUA_ClientInformation *> failedClients;
  bool asyncIsNeeded = false;
  for(CSinglyLinkedList<CUA_ClientInformation *>::Iterator itClientInformation = mIterationClients.begin(); itClientInformation != mIterationClients.end();
      ++itClientInformation) {
    CCriticalRegion criticalRegionClienMutex((*itClientInformation)->getMutex());
    if((*itClientInformation)->isAsyncNeeded()) {
      if(!(*itClientInformation)->executeAsyncCalls()) {
        failedClients.pushBack(*itClientInformation);
      } else {
        asyncIsNeeded = (*itClientInformation)->isAsyncNeeded();
      }
    }
    if(!isAlive()) {
      break;
    }
  }

  if(isAlive() && !failedClients.isEmpty()) {
    for(CSinglyLinkedList<CUA_ClientInformation *>::Iterator itClientInformation = failedClients.begin(); itClientInformation != failedClients.end();
        ++itClientInformation) {
      DEVLOG_ERROR("[OPC UA REMOTE]: There was a problem checking remote %s.\n", (*itClientInformation)->getEndpoint().getValue());

      //we cannot use COPC_UA_Client_IterationList::remove here because it locks mIterationClientsMutex
      CCriticalRegion newClientsRegion(mNewClientsMutex);
      CCriticalRegion criticalRegionClienMutex((*itClientInformation)->getMutex());
      mIterationClients.erase(*itClientInformation);
      mNewClients.erase(*itClientInformation); //client could still be in the newList
      (*itClientInformation)->uninitializeClient(); //reset all in client and pass it back to the connection handler
      (*itClientInformation)->configureClient();
      addClientToConnectionHandler(**itClientInformation);
    }
  }
  return asyncIsNeeded;
}

//************************** CONECTION HANDLER ************** //

COPC_UA_Remote_Handler::UA_ConnectionHandler::UA_ConnectionHandler(COPC_UA_Remote_Handler& paClientHandler) :
    mClientHandler(paClientHandler) {
}

COPC_UA_Remote_Handler::UA_ConnectionHandler::~UA_ConnectionHandler() {
}

bool COPC_UA_Remote_Handler::UA_ConnectionHandler::handleClients() {
  CCriticalRegion clientsClientsRegion(mIterationClientsMutex);
  CSinglyLinkedList<CUA_ClientInformation *> clientsToRemove;
  bool needsRetry = false;
  for(CSinglyLinkedList<CUA_ClientInformation *>::Iterator itClientInformation = mIterationClients.begin(); itClientInformation != mIterationClients.end();
      ++itClientInformation) {
    CCriticalRegion clientRegion((*itClientInformation)->getMutex());
    if((*itClientInformation)->handleClientState()) {
      clientsToRemove.pushBack(*itClientInformation);
    } else {
      needsRetry = true;
    }
    if((*itClientInformation)->someActionWasInitialized()) {
      mClientHandler.addClient(**itClientInformation);
    }
    if(!isAlive()) {
      break;
    }
  }

  if(isAlive() && !clientsToRemove.isEmpty()) {
    for(CSinglyLinkedList<CUA_ClientInformation *>::Iterator itClientInformation = clientsToRemove.begin(); itClientInformation != clientsToRemove.end();
        ++itClientInformation) {
      mIterationClients.erase(*itClientInformation);
    }
  }
  return needsRetry;
}

