// file: $isip/class/asr/AnnotationIndex/andx_02.cc
// version: $Id: andx_02.cc 7678 2002-02-01 14:49:32Z alphonso $
//

// isip include files
//
#include "AnnotationIndex.h"
#include <Console.h>


// method: diagnose
//
// arguments:
//  Integral::DEBUG level: (input) debug level for diagnostics
//
// return: a boolean value indicating status
//
boolean AnnotationIndex::diagnose(Integral::DEBUG level_a) {

  //----------------------------------------------------------------------
  //
  // 0. preliminaries
  //
  //----------------------------------------------------------------------

  // output the class name
  //
  if (level_a > Integral::NONE) {
    SysString output(L"diagnosing class ");
    output.concat(CLASS_NAME);
    output.concat(L": ");
    Console::put(output);
    Console::increaseIndention();
  }

  // --------------------------------------------------------------------
  //
  // 1. required public methods
  //
  // --------------------------------------------------------------------

  // set indentation
  //  
  if (level_a > Integral::NONE) {
    Console::put(L"testing required public methods...\n");
    Console::increaseIndention(); 
  }
  
  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }

  // declare some id's
  //
  String ancr_name_00(L"Anchor1");
  String ancr_name_01(L"Anchor2");
  String ancr_name_02(L"Anchor3");  
  String ancr_name_03(L"Anchor4");
 
  String anno_name_00(L"Annotation1");
  String anno_name_01(L"Annotation2");

  // declare some units
  //
  String unit_00(L"seconds");
  
  // declare some types
  //
  String type_00(L"type1");
  String type_01(L"type2");

  // declare some offsets
  //
  float offset_00 = 2.409875;
  float offset_01 = 2.649875;
  float offset_02 = 2.769875;
  float offset_03 = 3.273875;

  // declate some feature value pairs
  //
  String feat_00(L"feature1");
  String feat_01(L"feature2");

  String value_00(L"value1");
  String value_01(L"value2");
  
  // declare some anchors
  //
  Anchor ancr_00(ancr_name_00, offset_00, unit_00);
  Anchor ancr_01(ancr_name_01, offset_01, unit_00);
  Anchor ancr_02(ancr_name_02, offset_02, unit_00);
  Anchor ancr_03(ancr_name_03, offset_03, unit_00);
  
  // declare some annotations
  //
  Annotation anno_00(anno_name_00, &ancr_00, &ancr_01, type_00);
  Annotation anno_01(anno_name_01, &ancr_02, &ancr_03, type_01);  

  // declare some annotation indices
  //
  AnnotationIndex andx_00;
  
  // test the add annotation method
  //
  if (!andx_00.add(&anno_00)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  
  // test the exist annotation/anchor methods
  //
  if (!andx_00.existsAnnotation(anno_name_00)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (andx_00.existsAnnotation(anno_name_01)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }  

  if (!andx_00.existsAnchor(ancr_name_00)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (!andx_00.existsAnchor(ancr_name_01)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (andx_00.existsAnchor(ancr_name_02)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (andx_00.existsAnchor(ancr_name_03)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }    

  // test the add annotation method
  //  
  if (!andx_00.add(&anno_01)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }  

  // test the exist annotation/anchor methods
  //
  if (!andx_00.existsAnnotation(anno_name_00)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (!andx_00.existsAnnotation(anno_name_01)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }  

  if (!andx_00.existsAnchor(ancr_name_00)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (!andx_00.existsAnchor(ancr_name_01)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (!andx_00.existsAnchor(ancr_name_02)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (!andx_00.existsAnchor(ancr_name_03)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }

  // test the delete annotation methods
  //
  if (!andx_00.deleteAnnotation(&anno_00)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  
  // test the exist annotation/anchor method
  //
  if (andx_00.existsAnnotation(anno_name_00)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (!andx_00.existsAnnotation(anno_name_01)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }  

  if (!andx_00.existsAnchor(ancr_name_00)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (!andx_00.existsAnchor(ancr_name_01)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (!andx_00.existsAnchor(ancr_name_02)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (!andx_00.existsAnchor(ancr_name_03)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  
  // test the nearest offset method
  //
  if (!Integral::almostEqual(andx_00.getNearestOffset(offset_00), offset_00)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (!Integral::almostEqual(andx_00.getNearestOffset(offset_01), offset_01)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }      
  if (!Integral::almostEqual(andx_00.getNearestOffset(offset_02), offset_02)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (!Integral::almostEqual(andx_00.getNearestOffset(offset_03), offset_03)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }    
  if (!Integral::almostEqual(andx_00.getNearestOffset(2.39), offset_00)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (!Integral::almostEqual(andx_00.getNearestOffset(2.41), offset_00)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }  
  if (!Integral::almostEqual(andx_00.getNearestOffset(2.64), offset_01)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }  
  if (!Integral::almostEqual(andx_00.getNearestOffset(2.65), offset_01)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (!Integral::almostEqual(andx_00.getNearestOffset(2.76), offset_02)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (!Integral::almostEqual(andx_00.getNearestOffset(2.77), offset_02)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }      
  if (!Integral::almostEqual(andx_00.getNearestOffset(3.12), offset_03)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }  
  if (!Integral::almostEqual(andx_00.getNearestOffset(3.24), offset_03)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }  

  // test the get offset method
  //
  DoubleLinkedList<Annotation> annotations(DstrBase::USER);

  // this should return an empty list
  //
  andx_00.getByOffset(offset_00, annotations);
  if (annotations.length() != 0) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }

  // this should return an empty list
  //
  andx_00.getByOffset(offset_01, annotations);
  if (annotations.length() != 0) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }  
  
  // this should return a single annotation (anno_01)
  //
  andx_00.getByOffset(offset_02, annotations);
  if (annotations.length() != 1) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (annotations.getFirst() != &anno_01) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  
  // this should return a single annotation (anno_01)
  //
  andx_00.getByOffset(offset_03, annotations);  
  if (annotations.length() != 1) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (annotations.getFirst() != &anno_01) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  
  // test the get annotation offset method
  //
  Annotation* annotation;

  // this should return a null pointer
  //
  annotation = andx_00.getAnnotationByOffset(offset_00);  
  if (annotation != (Annotation*)NULL) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }

  // this should return a null pointer
  //
  annotation = andx_00.getAnnotationByOffset(offset_01);  
  if (annotation != (Annotation*)NULL) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }  

  // this should return a single annotation (anno_01)
  //
  annotation  = andx_00.getAnnotationByOffset(offset_02);
  if (annotation != &anno_01) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  
  // this should return a single annotation (anno_01)
  //
  annotation = andx_00.getAnnotationByOffset(offset_03);  
  if (annotation != &anno_01) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }

  // test the add/delete/exists features methods
  //
  AnnotationIndex andx_01;
  Annotation* anno_02 = new Annotation(anno_name_00, &ancr_00,
				       &ancr_01, type_00);

  // add the feature-value pairs to the annotation
  //
  anno_02->setFeature(feat_00, value_00);
  anno_02->setFeature(feat_01, value_01);  
  
  // insert an annotation
  //
  if (!andx_01.add(anno_02)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }

  // add some features to the annotation
  //
  if (!andx_01.addFeature(anno_02, feat_00, value_00)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (!andx_01.addFeature(anno_02, feat_01, value_01)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }  

  // check if the features exists
  //
  if (!andx_01.existsFeature(feat_00, value_00)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (!andx_01.existsFeature(feat_01, value_01)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }  

  // delete a feature form the index
  //
  if (!andx_01.deleteFeature(anno_02, feat_01)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }

  // test if the deletion was sucessfull
  //
  if (!andx_01.existsFeature(feat_00, value_00)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }
  if (andx_01.existsFeature(feat_01, value_01)) {
    return Error::handle(name(), L"diagnose", Error::TEST, __FILE__, __LINE__);
  }

  // clean up memory
  //
  delete anno_02;
  
  //---------------------------------------------------------------------
  //
  // 2. print completion message
  //
  //---------------------------------------------------------------------  

  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }
  
  if (level_a > Integral::NONE) {
    SysString output(L"diagnostics passed for class ");
    output.concat(name());
    output.concat(L"\n");
    Console::put(output);
  }

  // exit gracefully
  //
  return true;
}
