// file: $isip/class/algo/Algorithm/algo_05.cc
// version: $Id: algo_05.cc 10656 2008-01-04 19:40:30Z dom5 $
//

// system include files
//
#include <typeinfo>

// isip include files
//
#include "Algorithm.h"

#include <AlgorithmContainer.h>
#include <Calculus.h>
#include <Cepstrum.h>
#include <CoefficientLabel.h>
#include <Connection.h>
#include <Constant.h>
#include <Correlation.h>
#include <Covariance.h>
#include <DisplayData.h>
#include <DynamicFilter.h>
#include <Energy.h>
#include <Filter.h>
#include <FilterBank.h>
#include <FourierTransform.h>
#include <Generator.h>
#include <LogAreaRatio.h>
#include <Mask.h>
#include <Math.h>
#include <Output.h>
#include <Prediction.h>
#include <Reflection.h>
#include <Spectrum.h>
#include <Statistics.h>
#include <Window.h>
#include <Rps.h>
#include <Lyapunov.h>
#include <CorrelationIntegral.h>
#include <MutualInformation.h>
#include <CorrelationEntropy.h>
#include <CorrelationDimension.h>

// method: getType
//
// arguments: none
//  
// return: the type of the Algorithm
//
// this method gets the type of the current algorithm object
//
Algorithm::TYPES Algorithm::getType() const {

  return (TYPES)TYPES_MAP(virtual_algo_d->className());
}

// method: setType
//
// arguments:
//  TYPES type: (input) type of algorithm
//
// return: a boolean value indicating status
//
// this method sets the algorithm object according to the input type
//
boolean Algorithm::setType(TYPES type_a) {

  if (virtual_algo_d != (AlgorithmBase*)&NO_ALGORITHM) {
    return Error::handle(name(), L"setType", Error::MEM, __FILE__, __LINE__);
  }
  
  if (type_a == ALGORITHM_CONTAINER) {
    virtual_algo_d = new AlgorithmContainer();
  }
  else if (type_a == CALCULUS) {
    virtual_algo_d = new Calculus();
  }
  else if (type_a == CEPSTRUM) {
    virtual_algo_d = new Cepstrum();
  }
  else if (type_a == COEFFICIENT_LABEL) {
    virtual_algo_d = new CoefficientLabel();
  }
  else if (type_a == CONNECTION) {
    virtual_algo_d = new Connection();
  }
  else if (type_a == CORRELATION) {
    virtual_algo_d = new Correlation();
  }
  else if (type_a == CONSTANT) {
    virtual_algo_d = new Constant();
  }
  else if (type_a == COVARIANCE) {
    virtual_algo_d = new Covariance();
  }
  else if (type_a == DISPLAY_DATA) {
    virtual_algo_d = new DisplayData();
  }
  else if (type_a == DYNAMIC_FILTER) {
    virtual_algo_d = new DynamicFilter();
  }
  else if (type_a == ENERGY) {
    virtual_algo_d = new Energy();
  }
  else if (type_a == FILTER) {
    virtual_algo_d = new Filter();
  }
  else if (type_a == FILTER_BANK) {
    virtual_algo_d = new FilterBank();
  }
  else if (type_a == FOURIER_TRANSFORM) {
    virtual_algo_d = new FourierTransform();
  }
  else if (type_a == GENERATOR) {
    virtual_algo_d = new Generator();
  }
  else if (type_a == LOG_AREA_RATIO) {
    virtual_algo_d = new LogAreaRatio();
  }
  else if (type_a == MASK) {
    virtual_algo_d = new Mask();
  }
  else if (type_a == MATH) {
    virtual_algo_d = new Math();
  }
  else if (type_a == OUTPUT) {
    virtual_algo_d = new Output();
  }    
  else if (type_a == PREDICTION) {
    virtual_algo_d = new Prediction();
  }
  else if (type_a == REFLECTION) {
    virtual_algo_d = new Reflection();
  }
  else if (type_a == SPECTRUM) {
    virtual_algo_d = new Spectrum();
  }
  else if (type_a == STATISTICS) {
    virtual_algo_d = new Statistics();
  }
  else if (type_a == WINDOW) {
    virtual_algo_d = new Window();
  }
  else if (type_a == RPS) {
    virtual_algo_d = new Rps();
  }
  else if (type_a == LYAPUNOV) {
    virtual_algo_d = new Lyapunov();
  }
  else if (type_a == CORRELATION_INTEGRAL) {
    virtual_algo_d = new CorrelationIntegral();
  }  
  else if (type_a == MUTUAL_INFORMATION) {
    virtual_algo_d = new MutualInformation();
  }
  else if (type_a == CORRELATION_ENTROPY) {
    virtual_algo_d = new CorrelationEntropy();
  }  
  else if (type_a == CORRELATION_DIMENSION) {
    virtual_algo_d = new CorrelationDimension();
  }
  
  // invalid type
  //
  else {
    return Error::handle(name(), L"setType", Error::ENUM, __FILE__, __LINE__);
  }

  // exit gracefully
  //
  return true;
}

// method: getCLabelVariable
//
// arguments: none
//
// return: variable string from the CoefficientLabel
//
// this method retrieves the variable string from the CoefficientLabel
//
const String& Algorithm::getCLabelVariable() const {

  if (typeid(*virtual_algo_d) != typeid(CoefficientLabel)) {
    Error::handle(name(), L"getCLabelVariable", ERR, __FILE__,
		  __LINE__);
  }

  CoefficientLabel* clab = (CoefficientLabel*)virtual_algo_d;
  return clab->getVariable();
}

// method: getCLabelType
//
// arguments: none
//
// return: type parameter from the CoefficientLabel
//
// this method retrieves the type parameter from the CoefficientLabel
//
CoefficientLabel::TYPE Algorithm::getCLabelType() const {

  if (typeid(*virtual_algo_d) != typeid(CoefficientLabel)) {
    Error::handle(name(), L"getCLabelType", ERR, __FILE__,
		  __LINE__);
  }

  CoefficientLabel* clab = (CoefficientLabel*)virtual_algo_d;
  return clab->getType();
}

// method: getContainerGraphTag
//
// arguments: none
//
// return: graph tag parameter from the AlgorithmContainer
//
// this method retrieves the graph tag parameter from the AlgorithmContainer
//
long Algorithm::getContainerGraphTag() const {

  if (typeid(*virtual_algo_d) != typeid(AlgorithmContainer)) {
    Error::handle(name(), L"getContainerGraphTag", ERR, __FILE__,
		  __LINE__);
  }

  AlgorithmContainer* ctn = (AlgorithmContainer*)virtual_algo_d;
  return ctn->getGraphTag();
}

// method: apply
//
// arguments:
//  Vector<AlgorithmData>& output: (output) output data
//  const Vector< CircularBuffer<AlgorithmData> >& input: (input) input data
//
// return: logical error status
//
// this method calls the virtual apply method of the class pointer
//
boolean Algorithm::apply(Vector<AlgorithmData>& output_a,
			 const
			 Vector< CircularBuffer<AlgorithmData> >& input_a) {

  if (!virtual_algo_d->apply(output_a, input_a)) {
    virtual_algo_d->debug(L"algorithm");
    return Error::handle(name(), L"apply", ERR, __FILE__, __LINE__,
			 Error::WARNING);
  }
  return true;
}
