/** \file internal_engine_base.cpp .
-----------------------------------------------------------------------------


 * 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.

-----------------------------------------------------------------------------

   Description:

-----------------------------------------------------------------------------


-------------------------------------------------------------------------- */


/* ----------------------------------------------------------------------- */
/*       Include dependencies                                              */
/* ----------------------------------------------------------------------- */
//#define DEBUG_VERBOSE 1

#include "uima/pragmas.hpp"

#include "uima/macros.h"
#include "uima/internal_engine_base.hpp"
#include "uima/msg.h"
#include "uima/annotator_context.hpp"
#include "uima/log.hpp"
#include "uima/lowlevel_typesystem.hpp"
#include "uima/lowlevel_indexrepository.hpp"
#include "uima/casdefinition.hpp"
#include "uima/internal_casimpl.hpp"
#include "uima/trace.hpp"

/* ----------------------------------------------------------------------- */
/*       Constants                                                         */
/* ----------------------------------------------------------------------- */

/* ----------------------------------------------------------------------- */
/*       Forward declarations                                              */
/* ----------------------------------------------------------------------- */

/* ----------------------------------------------------------------------- */
/*       Types / Classes                                                   */
/* ----------------------------------------------------------------------- */

/* ----------------------------------------------------------------------- */
/*       Implementation                                                    */
/* ----------------------------------------------------------------------- */
namespace uima {
  namespace internal {

    uima::internal::EngineBase & EngineBase::promoteEngine( uima::AnalysisEngine & engine) {
      return (uima::internal::EngineBase&) engine;
    }

    EngineBase::EngineBase(AnnotatorContext & rANC, bool bOwnsANC,
                           bool bOwnsTAESpecififer,
                           uima::internal::CASDefinition & casDef, bool ownsCasDef)
        :
        iv_pAnnotatorContext( & rANC),
        iv_bOwnsANC(bOwnsANC),
        iv_bOwnsTAESpec(bOwnsTAESpecififer),
        iv_casDefinition( & casDef),
        iv_ownsCASDefinition(ownsCasDef) {
      iv_casHolder = NULL;
    }

    EngineBase::~EngineBase() {
      if (iv_bOwnsTAESpec) {
        delete iv_pAnnotatorContext->getTAESpec();
      }
      if (iv_bOwnsANC) {
        delete iv_pAnnotatorContext;
      }
      if (iv_ownsCASDefinition) {
        delete iv_casDefinition;
      }
      if (iv_casHolder) {
        delete iv_casHolder;
      }
    }

    /**
     * pretty simple CAS compatibility check: Just check if they
     * have the same type system and index definition.
     */
    void EngineBase::checkCASCompatibility(CAS const & cas) const {
      uima::internal::CASImpl const & tcasImpl = uima::internal::CASImpl::promoteCAS(cas);
      if ( (&tcasImpl.getHeap().getTypeSystem()) != (&iv_casDefinition->getTypeSystem())
           || (& tcasImpl.getIndexRepository().getIndexDefinition()) != (& iv_casDefinition->getIndexDefinition()) ) {
        UIMA_EXC_THROW_NEW(CASIncompatibilityException,
                           UIMA_ERR_ENGINE_INCOMPATIBLE_CAS,
                           UIMA_MSG_ID_EXC_INCOMPATIBLE_CAS,
                           UIMA_MSG_ID_EXCON_PROCESSING_CAS,
                           ErrorInfo::recoverable);
      }
    }


    bool EngineBase::checkAndSetCallingSequenceInitialize() {
      if (iv_state.getState() != EngineState::enEngineState_readyForInit) {
        return false;
      }
      iv_state.setToState(EngineState::enEngineState_readyForProcessOrReconfigOrDeinit);
      return true;
    }


    bool EngineBase::checkAndSetCallingSequenceDestroy() {
      if ( (iv_state.getState() != EngineState::enEngineState_readyForProcessOrReconfigOrDeinit) ) {
        return false;
      }

      iv_state.setToState(EngineState::enEngineState_readyForDeletion);
      return true;
    }

    bool EngineBase::checkAndSetCallingSequenceProcess() {
      UIMA_TPRINT("state: " << iv_state.getState());
      if (iv_state.getState() != EngineState::enEngineState_readyForProcessOrReconfigOrDeinit) {
        return false;
      }
      // dont change state
      return true;
    }


    bool EngineBase::checkAndSetCallingSequenceReconfigure() {
      if ( iv_state != EngineState::enEngineState_readyForProcessOrReconfigOrDeinit) {
        return false;
      }
      // dont change state
      return true;
    }

    TyErrorId EngineBase::logError(util::Trace & rclTrace, TyErrorId utErrorId) {
      if (utErrorId != UIMA_ERR_NONE) {
        rclTrace.dump(_TEXT("Error:"), (size_t) utErrorId);
      }
      return(utErrorId);
    }



    bool EngineBase::isInitialized(void) const {
      switch (iv_state.getState()) {
      case EngineState::enEngineState_readyForInit :
      case EngineState::enEngineState_readyForDeletion :
        return false;
      case EngineState::enEngineState_readyForProcessOrReconfigOrDeinit :
        return true;
      }
      assert(false);
      return false;
    }

    CAS * EngineBase::newCAS() const {
      assert( EXISTS(iv_casDefinition) );
      assert( EXISTS(iv_pAnnotatorContext) );
      CAS* tmpCas = uima::internal::CASImpl::createCASImpl(* CONST_CAST(uima::internal::CASDefinition*, iv_casDefinition), *iv_pAnnotatorContext);
      return tmpCas->getInitialView();
    }


    void EngineBase::destroyIfNeeded() {
      util::Trace                 clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);

      try {
        if (iv_state == EngineState::enEngineState_readyForProcessOrReconfigOrDeinit) {
          destroy();
          iv_state.assertMatch(EngineState::enEngineState_readyForDeletion);
        }
      } catch (ExcWinCException & rclException) {
        // windows "exceptions" are really abort signals: we re-throw for app to handle
        throw rclException;
      } catch (Exception & rclException) {
        clTrace.dump("Unexpected UIMACPP exception");
        clTrace.dump(rclException.asString().c_str());
        assertWithMsg(false, _TEXT("Unexpected UIMACPP exception in engine destructor"));   //lint !e506: Constant value Boolean
      } catch (std::exception & rclException) {
        clTrace.dump("ANSI C++ exception");
        clTrace.dump(rclException.what());
        assertWithMsg(false, _TEXT("Unexpected ANSI C++ exception in engine destructor"));   //lint !e506: Constant value Boolean
      }
#ifdef NDEBUG
      catch (...) {
        /* this should never occur!!! */
        clTrace.dump(_TEXT("Unexpected exception"));
        assertWithMsg(false, _TEXT("Unexpected unknown exception in engine destructor"));   //lint !e506: Constant value Boolean
      }
#endif
    }


    /**
     * Gathers all output capabilities from the TAE specifier.
     * This result spec is implicitly assumed when calling process(CAS) without a result spec.
     */
    TyErrorId EngineBase::initializeCompleteResultSpec() {
      iv_completeResultSpec.clear();

      assert( EXISTS(iv_casDefinition) );
      uima::TypeSystem const & rTypeSystem = iv_casDefinition->getTypeSystem();

      AnnotatorContext const & crANC = getAnnotatorContext();

      AnalysisEngineMetaData::TyVecpCapabilities const & crVecCaps = crANC.getTaeSpecifier().getAnalysisEngineMetaData()->getCapabilites();
      AnalysisEngineMetaData::TyVecpCapabilities::const_iterator citCaps;

      for (citCaps = crVecCaps.begin(); citCaps != crVecCaps.end(); ++citCaps) {
        Capability const * cpCap = * citCaps;
        Capability::TyVecCapabilityTofs const & crTypes = cpCap->getCapabilityTypes(Capability::OUTPUT);
        Capability::TyVecCapabilityTofs::const_iterator citTOFs;
        for (citTOFs = crTypes.begin(); citTOFs != crTypes.end(); ++citTOFs) {
          Type t = rTypeSystem.getType( *citTOFs );
          if (! t.isValid() ) {
            ErrorInfo errInf(
              ErrorMessage(UIMA_MSG_ID_UNKNOWN_FEATURE_IN_CAPBILITY_SPEC,(*citTOFs)),
              UIMA_ERR_ANNOTATOR_MGR_CONFIG_INVALID_RESULTSPECIFICATION,
              ErrorInfo::unrecoverable);
            getAnnotatorContext().getLogger().logError(errInf);
            return UIMA_ERR_ANNOTATOR_MGR_CONFIG_INVALID_RESULTSPECIFICATION;
          }
          iv_completeResultSpec.add(t);
        }

        Capability::TyVecCapabilityTofs const & crFeatures = cpCap->getCapabilityFeatures(Capability::OUTPUT);
        for (citTOFs = crFeatures.begin(); citTOFs != crFeatures.end(); ++citTOFs) {
          Feature f = rTypeSystem.getFeatureByFullName(*citTOFs);
          if (! f.isValid() ) {
            ErrorInfo errInf(
              ErrorMessage(UIMA_MSG_ID_UNKNOWN_FEATURE_IN_CAPBILITY_SPEC,(*citTOFs)),
              UIMA_ERR_ANNOTATOR_MGR_CONFIG_INVALID_RESULTSPECIFICATION,
              ErrorInfo::unrecoverable);
            getAnnotatorContext().getLogger().logError(errInf);
            return UIMA_ERR_ANNOTATOR_MGR_CONFIG_INVALID_RESULTSPECIFICATION;
          }
          iv_completeResultSpec.add(f);
        }

      }
      return UIMA_ERR_NONE;
    }


    TyErrorId EngineBase::initialize(AnalysisEngineDescription const & specifier) {
      try {
        util::Trace                clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);

        if (!checkAndSetCallingSequenceInitialize()) {
          return logError(clTrace, UIMA_ERR_ENGINE_INVALID_CALLING_SEQUENCE);
        }
        assert( (& specifier) == (&iv_pAnnotatorContext->getTaeSpecifier()));
        // call implementation in subclass
        TyErrorId utErrorId = initializeImpl(specifier);
        if (utErrorId != UIMA_ERR_NONE) {
          destroy();
          return utErrorId;
        }

        utErrorId = initializeCompleteResultSpec();
        if (utErrorId != UIMA_ERR_NONE) {
          destroy();
          return utErrorId;
        }

        int numCasRequired =  getCasInstancesRequiredImpl();
        if (numCasRequired > 0) {
          utErrorId = iv_pAnnotatorContext->defineCASPool(numCasRequired);
        }

        return utErrorId;
      } catch (Exception & rclException) {
        getAnnotatorContext().getLogger().logError(rclException.getErrorInfo() );
        return rclException.getErrorInfo().getErrorId();
      }

    }


    TyErrorId EngineBase::reinitTypeSystem() {
      try {
        util::Trace                clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
        TyErrorId utErrorId = reinitTypeSystemImpl();
        if (utErrorId != UIMA_ERR_NONE) {
          destroy();
          return utErrorId;
        }

        // we have to re-initialize the result spec since the types and features
        // may have changed.
        utErrorId = initializeCompleteResultSpec();
        if (utErrorId != UIMA_ERR_NONE) {
          destroy();
          return utErrorId;
        }
        return utErrorId;
      } catch (Exception & rclException) {
        getAnnotatorContext().getLogger().logError(rclException.getErrorInfo() );
        return rclException.getErrorInfo().getErrorId();
      }

    }


    ResultSpecification const & EngineBase::getCompleteResultSpecification() const {
      return iv_completeResultSpec;
    }


    TyErrorId EngineBase::destroy() {
      try {
        util::Trace                clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);

        if (!checkAndSetCallingSequenceDestroy()) {
          return logError(clTrace, UIMA_ERR_ENGINE_INVALID_CALLING_SEQUENCE);
        }
        return destroyImpl();
      } catch (Exception & rclException) {
        getAnnotatorContext().getLogger().logError(rclException.getErrorInfo() );
        return rclException.getErrorInfo().getErrorId();
      }
    }

    TyErrorId EngineBase::reconfigure() {
      try {
        util::Trace                clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);

        if (!checkAndSetCallingSequenceReconfigure()) {
          return logError(clTrace, UIMA_ERR_ENGINE_INVALID_CALLING_SEQUENCE);
        }
        return reconfigureImpl();
      } catch (Exception & rclException) {
        getAnnotatorContext().getLogger().logError(rclException.getErrorInfo() );
        return rclException.getErrorInfo().getErrorId();
      }

    }


    TyErrorId EngineBase::process(CAS & cas) {
      try {
        AnalysisEngine * engine = this;
        return engine->process(cas, getCompleteResultSpecification());
      } catch (Exception & rclException) {
        getAnnotatorContext().getLogger().logError(rclException.getErrorInfo() );
        UIMA_EXC_RETHROW(rclException,0);
        ///return rclException.getErrorInfo().getErrorId();
      }

    }

    TyErrorId EngineBase::process(CAS & cas, ResultSpecification const & resultSpec) {
      try {
        util::Trace                clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);

        if (!checkAndSetCallingSequenceProcess()) {
          return logError(clTrace, UIMA_ERR_ENGINE_INVALID_CALLING_SEQUENCE);
        }
        // (ee) WHY DO THIS CHECK???
        //checkCASCompatibility(cas);

        // Removed code that used to skip the processing if the document
        // was empty, since not all Sofas have local text. (bll)

        return processImpl(cas, resultSpec);
      } catch (Exception & rclException) {
        getAnnotatorContext().getLogger().logError(rclException.getErrorInfo() );
        //return rclException.getErrorInfo().getErrorId();
        UIMA_EXC_RETHROW(rclException,0);
      }

    }


    TyErrorId EngineBase::batchProcessComplete() {
      try {
        util::Trace                clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);

        if (!checkAndSetCallingSequenceProcess()) {
          return logError(clTrace, UIMA_ERR_ENGINE_INVALID_CALLING_SEQUENCE);
        }
        return batchProcessCompleteImpl();
      } catch (Exception & rclException) {
        getAnnotatorContext().getLogger().logError(rclException.getErrorInfo() );
        return rclException.getErrorInfo().getErrorId();
      }

    }

    TyErrorId EngineBase::collectionProcessComplete() {
      try {
        util::Trace                clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);

        if (!checkAndSetCallingSequenceProcess()) {
          return logError(clTrace, UIMA_ERR_ENGINE_INVALID_CALLING_SEQUENCE);
        }
        return collectionProcessCompleteImpl();
      } catch (Exception & rclException) {
        getAnnotatorContext().getLogger().logError(rclException.getErrorInfo() );
        return rclException.getErrorInfo().getErrorId();
      }

    }

    bool EngineBase::hasNext() {
      try {
        util::Trace                clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
        /** why do this ?? (bi)
        if (!checkAndSetCallingSequenceProcess()) {
           logError(clTrace, UIMA_ERR_ENGINE_INVALID_CALLING_SEQUENCE);
           return false;
        } **/
        return hasNextImpl();
      } catch (Exception & rclException) {
        getAnnotatorContext().getLogger().logError(rclException.getErrorInfo() );
        throw rclException;
      }
    }

    CAS &  EngineBase::next() {
      try {
        util::Trace                clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
        /** why do this (bi)
        if (!checkAndSetCallingSequenceProcess()) {
           logError(clTrace, UIMA_ERR_ENGINE_INVALID_CALLING_SEQUENCE);
        } **/
        return nextImpl();
      } catch (Exception & rclException) {
        getAnnotatorContext().getLogger().logError(rclException.getErrorInfo() );
        //return rclException.getErrorInfo().getErrorId();
        throw rclException;
      }
    }

    int  EngineBase::getCasInstancesRequired() {
      try {
        util::Trace                clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);

        if (!checkAndSetCallingSequenceProcess()) {
          logError(clTrace, UIMA_ERR_ENGINE_INVALID_CALLING_SEQUENCE);
          return 0;
        }
        return getCasInstancesRequiredImpl();
      } catch (Exception & rclException) {
        getAnnotatorContext().getLogger().logError(rclException.getErrorInfo() );
        //return rclException.getErrorInfo().getErrorId();
        throw rclException;
      }
    }

    CASIterator EngineBase::processAndOutputNewCASes(CAS & cas) {
      try {
        util::Trace                clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);

        if (!checkAndSetCallingSequenceProcess()) {
          logError(clTrace, UIMA_ERR_ENGINE_INVALID_CALLING_SEQUENCE);

          UIMA_EXC_THROW_NEW(CASIteratorException,
                             UIMA_ERR_ENGINE_INVALID_CALLING_SEQUENCE,
                             UIMA_MSG_ID_EXCON_CALLING_ANNOTATOR_FUNCTION,
                             UIMA_MSG_ID_EXCON_CALLING_ANNOTATOR_FUNCTION,
                             ErrorInfo::unrecoverable);
        }
        TyErrorId rc = process(cas);
        if (rc != UIMA_ERR_NONE) {
          UIMA_EXC_THROW_NEW(CASIteratorException,
                             UIMA_ERR_PROCESS_OUTPUT_CAS,
                             UIMA_MSG_ID_EXCON_CALLING_ANNOTATOR_FUNCTION,
                             UIMA_MSG_ID_EXCON_CALLING_ANNOTATOR_FUNCTION,
                             ErrorInfo::unrecoverable);
        }
        return CASIterator(this);
      } catch (Exception & rclException) {
        getAnnotatorContext().getLogger().logError(rclException.getErrorInfo() );
        //return rclException.getErrorInfo().getErrorId();
        throw rclException;
      }
    }

    TyErrorId EngineBase::batchProcessCompleteImpl() {
      return UIMA_ERR_NOT_YET_IMPLEMENTED;
    }

    TyErrorId EngineBase::collectionProcessCompleteImpl() {
      return UIMA_ERR_NOT_YET_IMPLEMENTED;
    }

  }
}

/* ----------------------------------------------------------------------- */



