/** \file internal_primitive_engine.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                                              */
/* ----------------------------------------------------------------------- */
#include "uima/pragmas.hpp"
#include "uima/macros.h"
#include "uima/internal_primitive_engine.hpp"
#include "uima/capability.hpp"
#include "uima/casdefinition.hpp"
#include "uima/trace.hpp"
#include "uima/internal_capability_container.hpp"
#include "uima/lowlevel_typesystem.hpp"
#include "uima/annotator_mgr.hpp"
#include "uima/log.hpp"
#include "uima/msg.h"
#include "uima/cas.hpp"
#include "uima/filename.hpp"

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

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

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

/* ----------------------------------------------------------------------- */
/*       Implementation                                                    */
/* ----------------------------------------------------------------------- */
using namespace std;
namespace uima {
  namespace internal {

    PrimitiveEngine::PrimitiveEngine(AnnotatorContext & rAnnContext, bool bOwnsANC,
                                     bool bOwnsTAESpec,
                                     uima::internal::CASDefinition & casdef, bool ownsCasDef,
                                     bool ) :
        EngineBase(rAnnContext, bOwnsANC, bOwnsTAESpec, casdef, ownsCasDef),
        iv_pAnnotator(NULL),
        iv_pCapContainer(NULL) {}

    PrimitiveEngine::~PrimitiveEngine() {
      destroyIfNeeded();
    }


    bool isTypeName(TCHAR const * cpName) {
      icu::UnicodeString target(cpName);
      int iIndex = target.indexOf((UChar)':');
      return iIndex == -1;
    }

    TyErrorId PrimitiveEngine::initializeImpl(AnalysisEngineDescription const & crEngineDescription) {
      util::Trace trace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
      TyErrorId utErrorId = UIMA_ERR_NONE;
      UnicodeStringRef refDLLName(crEngineDescription.getAnnotatorImpName());
      string strAnnotatorName;

      refDLLName.extract( strAnnotatorName, CCSID::getDefaultName() );

      UnicodeStringRef refSymbolicName(crEngineDescription.getAnalysisEngineMetaData()->getName() );
      string strSymbolicName;
      refSymbolicName.extract( strSymbolicName, CCSID::getDefaultName() );


      util::Filename dllFileName( strAnnotatorName.c_str() );
      iv_pAnnotator = new AnnotatorProxy(dllFileName, strSymbolicName.c_str() );
      if ( iv_pAnnotator == NULL) {
        return UIMA_ERR_ENGINE_OUT_OF_MEMORY;
      }

      if (! iv_pAnnotator->isLoadedDelayed()) {
        utErrorId = iv_pAnnotator->load();
        if (utErrorId == UIMA_ERR_NONE) {
          utErrorId = iv_pAnnotator->init(getAnnotatorContext());
        }
      } else {
        assertWithMsg(false, "delayed loading not yet implemented");
        return UIMA_ERR_NOT_YET_IMPLEMENTED;
      }
      if (utErrorId != UIMA_ERR_NONE) {
        if (utErrorId == UIMA_ERR_ANNOTATOR_COULD_NOT_FIND ) {
          TyMessageId utErrorMsg = UIMA_MSG_ID_ANNOTATOR_COULD_NOT_FIND;
          ErrorMessage errMsg(utErrorMsg);
          errMsg.addParam(iv_pAnnotator->getFilename());
          ErrorInfo err(errMsg, utErrorId, ErrorInfo::unrecoverable);
          getAnnotatorContext().getLogger().logError(err);
        } else if (utErrorId == UIMA_ERR_ANNOTATOR_MISSING_CREATE) {
          TyMessageId utErrorMsg = UIMA_MSG_ID_ANNOTATOR_COULD_NOT_FIND_MAKEAE;
          ErrorMessage errMsg(utErrorMsg);
          errMsg.addParam(iv_pAnnotator->getFilename());
          if (iv_pAnnotator->getErrorMsg() != NULL) {
            errMsg.addParam(iv_pAnnotator->getErrorMsg());
          }
          ErrorInfo err(errMsg, utErrorId, ErrorInfo::unrecoverable);
          getAnnotatorContext().getLogger().logError(err);
        }  else if (utErrorId == UIMA_ERR_ANNOTATOR_COULD_NOT_LOAD) {
          TyMessageId utErrorMsg = UIMA_MSG_ID_ANNOTATOR_COULD_NOT_LOAD;
          ErrorMessage errMsg(utErrorMsg);
          errMsg.addParam(iv_pAnnotator->getFilename());
          if (iv_pAnnotator->getErrorMsg() != NULL) {
            errMsg.addParam(iv_pAnnotator->getErrorMsg());
          }
          ErrorInfo err(errMsg, utErrorId, ErrorInfo::unrecoverable);
          getAnnotatorContext().getLogger().logError(err);
        }
        // we do not need to log detailed messages for the other errors
        // like "could not init" this has been done already by the annotators
        destroy();
        return utErrorId;
      }

      iv_pCapContainer = new internal::CapabilityContainer();
      assert( EXISTS(iv_pCapContainer) );

      vector<Capability*> const & crCapabilities = getAnnotatorContext().getTaeSpecifier().getAnalysisEngineMetaData()->getCapabilites();

      UIMA_TPRINT("number capabilities: " << crCapabilities.size());
      assert( EXISTS(iv_casDefinition) );
      iv_pCapContainer->init(crCapabilities, iv_casDefinition->getTypeSystem());

      return typeSystemInitImpl();
    }


    TyErrorId PrimitiveEngine::typeSystemInitImpl() {
      util::Trace trace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
      try {
        UIMA_TPRINT("Processing annotator: " << iv_pAnnotator->getSymbolicName() );
        assert( EXISTS(iv_pAnnotator) );
        return iv_pAnnotator->typeSystemInit(iv_casDefinition->getTypeSystem() );
      } catch (Exception & rclException) {
        getAnnotatorContext().getLogger().logError(rclException.getErrorInfo() );
        return rclException.getErrorInfo().getErrorId();
      }

    }

    TyErrorId PrimitiveEngine::processImpl(CAS & cas, ResultSpecification const & crResultSpec) {
      util::Trace trace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);

      UIMA_TPRINT("Processing annotator: " << iv_pAnnotator->getSymbolicName() );
      assert( EXISTS(iv_pAnnotator) );
      bool bCallAnnotator = true;
      DocumentFS docfs = cas.getDocumentAnnotation();
      if (isTopLevelEngine()&& docfs.isValid()) {
        vector<TypeOrFeature> tofsToBeRemoved;
        if (! AnnotatorManager::shouldEngineBeCalled(*iv_pCapContainer,
            crResultSpec,
            docfs.getLanguage(),
            tofsToBeRemoved) ) {
          bCallAnnotator = false;
        }
        AnnotatorContext & rANC = getAnnotatorContext();
        AnalysisEngineDescription const & crTAESpecifier = rANC.getTaeSpecifier();
        FlowConstraints const * pFlow = crTAESpecifier.getAnalysisEngineMetaData()->getFlowConstraints();
        if (pFlow == NULL) {
          bCallAnnotator = true;
        } else {
          FlowConstraints * flow = CONST_CAST(FlowConstraints *, pFlow);
          FlowConstraints::EnFlowType flowType = flow->getFlowConstraintsType();
          //if FixedFlow specified all engines are always called so reset callEngine is true
          if (flowType == FlowConstraints::FIXED) {
            bCallAnnotator = true;
          }
        }
      }
      if (bCallAnnotator) {
        // link CAS to current component
        cas.setCurrentComponentInfo(&getAnnotatorContext());
        try {
          iv_pAnnotator->processDocument(cas, crResultSpec);
        } catch (Exception e) {
          UIMA_EXC_RETHROW(e,0);
        }
      }
      // if annotator should not be called is not really an error
      return UIMA_ERR_NONE;
    }

    TyErrorId PrimitiveEngine::destroyImpl()  {
      util::Trace trace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);

      TyErrorId utErrorId = UIMA_ERR_NONE;
      if (iv_pAnnotator != NULL ) {
        if (iv_pAnnotator->isInitialized()) {
          assert( iv_pAnnotator->isValid() );
          utErrorId = iv_pAnnotator->deInit();
        }
        delete iv_pAnnotator;
        iv_pAnnotator = NULL;
      }
      if (iv_pCapContainer != NULL) {
        delete iv_pCapContainer;
        iv_pCapContainer = NULL;
      }
      return utErrorId;
    }

    TyErrorId PrimitiveEngine::reconfigureImpl() {
      util::Trace trace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
      return iv_pAnnotator->reConfig();
    }

    TyErrorId PrimitiveEngine::batchProcessCompleteImpl() {
      util::Trace trace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
      return iv_pAnnotator->batchProcessComplete();
    }

    TyErrorId PrimitiveEngine::collectionProcessCompleteImpl() {
      util::Trace trace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
      return iv_pAnnotator->collectionProcessComplete();
    }

    bool PrimitiveEngine::hasNextImpl() {
      util::Trace trace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
      return iv_pAnnotator->hasNext();
    }

    CAS & PrimitiveEngine::nextImpl() {
      util::Trace trace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
      return iv_pAnnotator->next();
    }

    int PrimitiveEngine::getCasInstancesRequiredImpl() {
      util::Trace trace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_ENGINE);
      return iv_pAnnotator->getCasInstancesRequired();
    }

#ifdef UIMA_DEBUG_ANNOTATOR_TIMING

    void PrimitiveEngine::displayTimingData(util::ConsoleUI const & crConsole, bool bVerbose) const {
#ifndef NDEBUG
      crConsole.warning("timing data not yet available for primitive engines");
#endif
    }

#endif

  }
}

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



