/***********************************************************************
 * © 2016 and later: Unicode, Inc. and others.
 * License & terms of use: http://www.unicode.org/copyright.html
 *
 ***********************************************************************
 ***********************************************************************
 * COPYRIGHT:
 * Copyright (C) 2001-2016 International Business Machines Corporation
 * and others. All Rights Reserved.
 *
 ***********************************************************************/
/********************************************************************************
*
* File ubrkperf.cpp
*
* Modification History:
*        Name                     Description
*     Vladimir Weinstein          First Version, based on collperf
*
*********************************************************************************
*/

#include "cmemory.h"
#include "ubrkperf.h"
#include "uoptions.h"
#include <stdio.h>


#if 0
#if U_PLATFORM_IS_DARWIN_BASED
#include <ApplicationServices/ApplicationServices.h>
enum{
  kUCTextBreakAllMask = (kUCTextBreakClusterMask | kUCTextBreakWordMask | kUCTextBreakLineMask)
    };
UCTextBreakType breakTypes[4] = {kUCTextBreakCharMask, kUCTextBreakClusterMask, kUCTextBreakWordMask, kUCTextBreakLineMask};
TextBreakLocatorRef breakRef;
UCTextBreakType macBreakType;

void createMACBrkIt() {
  OSStatus status = noErr;
  LocaleRef lref;
  status = LocaleRefFromLocaleString(opt_locale, &lref);
  status = UCCreateTextBreakLocator(lref, 0, kUCTextBreakAllMask, (TextBreakLocatorRef*)&breakRef);
  if(opt_char == true) {
    macBreakType = kUCTextBreakClusterMask;
  } else if(opt_word == true) {
    macBreakType = kUCTextBreakWordMask;
  } else if(opt_line == true) {
    macBreakType = kUCTextBreakLineMask;
  } else if(opt_sentence == true) {
    // error
    // brkit = BreakIterator::createSentenceInstance(opt_locale, status);
  } else {
    // default is character iterator
    macBreakType = kUCTextBreakClusterMask;
      }
}
#endif


void doForwardTest() {
  if (opt_terse == false) {
    printf("Doing the forward test\n");
  }
  int32_t noBreaks = 0;
  int32_t i = 0;
  unsigned long startTime = timeGetTime();
  unsigned long elapsedTime = 0;
  if(opt_icu) {
    createICUBrkIt();
    brkit->setText(text);
    brkit->first();
    if (opt_terse == false) {
      printf("Warmup\n");
    }
    while(brkit->next() != BreakIterator::DONE) {
      noBreaks++;
    }
  
    if (opt_terse == false) {
      printf("Measure\n");
    } 
    startTime = timeGetTime();
    for(i = 0; i < opt_loopCount; i++) {
      brkit->first();  
      while(brkit->next() != BreakIterator::DONE) {
      }
    }

    elapsedTime = timeGetTime()-startTime;
  } else if(opt_mac) {
#if U_PLATFORM_IS_DARWIN_BASED
    createMACBrkIt();
    UniChar* filePtr = text;
    OSStatus status = noErr;
    UniCharCount startOffset = 0, breakOffset = 0, numUniChars = textSize;
    startOffset = 0;
    //printf("\t---Search forward--\n");
			
    while (startOffset < numUniChars)
    {
	status = UCFindTextBreak(breakRef, macBreakType, kUCTextBreakLeadingEdgeMask, filePtr, numUniChars,
                               startOffset, &breakOffset);
      //require_action(status == noErr, EXIT, printf( "**UCFindTextBreak failed: startOffset %d, status %d\n", (int)startOffset, (int)status));
      //require_action((breakOffset <= numUniChars),EXIT, printf("**UCFindTextBreak breakOffset too big: startOffset %d, breakOffset %d\n", (int)startOffset, (int)breakOffset));
				
      // Output break
      //printf("\t%d\n", (int)breakOffset);
				
      // Increment counters
	noBreaks++;
      startOffset = breakOffset;
    }
    startTime = timeGetTime();
    for(i = 0; i < opt_loopCount; i++) {
      startOffset = 0;
			
      while (startOffset < numUniChars)
	{
	  status = UCFindTextBreak(breakRef, macBreakType, kUCTextBreakLeadingEdgeMask, filePtr, numUniChars,
				   startOffset, &breakOffset);
	  // Increment counters
	  startOffset = breakOffset;
	}
    }
    elapsedTime = timeGetTime()-startTime;
    UCDisposeTextBreakLocator(&breakRef);
#endif


  }


  if (opt_terse == false) {
  int32_t loopTime = (int)(float(1000) * ((float)elapsedTime/(float)opt_loopCount));
      int32_t timePerCU = (int)(float(1000) * ((float)loopTime/(float)textSize));
      int32_t timePerBreak = (int)(float(1000) * ((float)loopTime/(float)noBreaks));
      printf("forward break iteration average loop time %d\n", loopTime);
      printf("number of code units %d average time per code unit %d\n", textSize, timePerCU);
      printf("number of breaks %d average time per break %d\n", noBreaks, timePerBreak);
  } else {
      printf("time=%d\nevents=%d\nsize=%d\n", elapsedTime, noBreaks, textSize);
  }


}




#endif

UPerfFunction* BreakIteratorPerformanceTest::TestICUForward()
{
  return new ICUForward(locale, m_mode_, m_file_, m_fileLen_);
}

UPerfFunction* BreakIteratorPerformanceTest::TestICUIsBound()
{
  return new ICUIsBound(locale, m_mode_, m_file_, m_fileLen_);
}

UPerfFunction* BreakIteratorPerformanceTest::TestDarwinForward()
{
  return NULL;
}

UPerfFunction* BreakIteratorPerformanceTest::TestDarwinIsBound()
{
  return NULL;
}

UPerfFunction* BreakIteratorPerformanceTest::runIndexedTest(int32_t index, UBool exec,
												   const char *&name, 
												   char* par) 
{
    switch (index) {
        TESTCASE(0, TestICUForward);
		TESTCASE(1, TestICUIsBound);
		TESTCASE(2, TestDarwinForward);
		TESTCASE(3, TestDarwinIsBound);
        default: 
            name = ""; 
            return NULL;
    }
    return NULL;
}

UOption options[]={
                      UOPTION_DEF( "mode",        'm', UOPT_REQUIRES_ARG)
                  };


BreakIteratorPerformanceTest::BreakIteratorPerformanceTest(int32_t argc, const char* argv[], UErrorCode& status)
: UPerfTest(argc,argv,status),
m_mode_(NULL),
m_file_(NULL),
m_fileLen_(0)
{

    _remainingArgc = u_parseArgs(_remainingArgc, (char**)argv, UPRV_LENGTHOF(options), options);


    if(options[0].doesOccur) {
      m_mode_ = options[0].value;
      switch(options[0].value[0]) {
      case 'w' : 
      case 'c' :
      case 's' :
      case 'l' :
        break;
      default:
        status = U_ILLEGAL_ARGUMENT_ERROR;
        break;
      }
    } else {
      status = U_ILLEGAL_ARGUMENT_ERROR;
    }

    m_file_ = getBuffer(m_fileLen_, status);

    if(status== U_ILLEGAL_ARGUMENT_ERROR){
       fprintf(stderr, gUsageString, "ubrkperf");
       fprintf(stderr, "\t-m or --mode        Required mode for breakiterator: char, word, line or sentence\n");

       return;
    }

    if(U_FAILURE(status)){
        fprintf(stderr, "FAILED to create UPerfTest object. Error: %s\n", u_errorName(status));
        return;
    }
}

BreakIteratorPerformanceTest::~BreakIteratorPerformanceTest()
{
}


//----------------------------------------------------------------------------------------
//
//    Main   --  process command line, read in and pre-process the test file,
//                 call other functions to do the actual tests.
//
//----------------------------------------------------------------------------------------
int main(int argc, const char** argv) {
    UErrorCode status = U_ZERO_ERROR;
    BreakIteratorPerformanceTest test(argc, argv, status);
    if(U_FAILURE(status)){
        return status;
    }
    if(test.run()==false){
        fprintf(stderr,"FAILED: Tests could not be run please check the arguments.\n");
        return -1;
    }
    return 0;
}
