#include "../test.h"
#include "CLucene/util/dirent.h"

#ifdef _UCS2
  void _Index(IndexWriter* ndx,char* file){
  	    char path[CL_MAX_PATH];
  	    TCHAR tlang[20];
		char* srcdirectory=CLUCENE_LOCATION "utf8text";

		strcpy(path,srcdirectory);
		strcat(path,"/");
		strcat(path,file);
		strcat(path,"_utf8.txt");
		
		STRCPY_AtoT(tlang,file,CL_MAX_PATH);

        Document doc;
		doc.add(*Field::Keyword(_T("language"),tlang));	   
		doc.add(*Field::Text(_T("contents"),_CLNEW FileReader(path,Reader::ENCODING_UTF8)));
		ndx->addDocument(&doc);
  }
  void _Search(CuTest *tc, IndexSearcher* srch, Analyzer* analyzer, char* file, char* query){
	TCHAR tlang[20];
	STRCPY_AtoT(tlang,file,CL_MAX_PATH);
	
	TCHAR tquery[80];
	lucene_utf8towcs(tquery,query,80);

  	Query* q = QueryParser::parse(tquery,_T("contents"), analyzer);
  	Hits* h = srch->search(q);
  	CLUCENE_ASSERT( h->length() == 1 );
  	
    Document& doc = h->doc(0);
  	CLUCENE_ASSERT( _tcscmp(doc.get(_T("language")), tlang)==0 );

    _CLDELETE(q);
    _CLDELETE(h);
  }

	void testUTF8(CuTest *tc) {
        RAMDirectory ram;
        Directory* pram = &ram;
        SimpleAnalyzer a;
		IndexWriter ndx(&ram,&a,true);
		_Index(&ndx,"arabic");
		/*_Index(&ndx,"chinese");
		_Index(&ndx,"czech");
		_Index(&ndx,"english");
		_Index(&ndx,"french");
		_Index(&ndx,"german");
		_Index(&ndx,"greek");
		_Index(&ndx,"hebrew");
		_Index(&ndx,"japanese");
		_Index(&ndx,"korean");
		_Index(&ndx,"polish");
		_Index(&ndx,"russian");*/
        ndx.close();

        /*IndexSearcher srch(&ram);
		_Search(tc,&srch,&a,"arabic", "\xef\xbb\x9e\xef\xbb\xb4\xef\xbb\xa4\xef\xbb\xb3\xef\xba\xad"); //????? - arabic
		_Search(tc,&srch,&a,"chinese", "\xe5\x95\xa4\xe9\x85\x92"); //?? - chinese
		_Search(tc,&srch,&a,"czech", "Bud\xc4\x9bjovick\xc3\xbd" ); //Budejovický - czech
		
      _Search(tc,&srch,&a,"english", "google"); //English - google
      _Search(tc,&srch,&a,"french", "r\xc3\xa9put\xc3\xa9"); //réputé - french
		_Search(tc,&srch,&a,"german", "k\xc3\xb6nnen"); //können - german
		_Search(tc,&srch,&a,"greek", "\xcf\x83\xcf\x84\xce\xb5\xce\xaf\xce\xbb\xcf\x84\xce\xb5"); //ste??te - greek
		_Search(tc,&srch,&a,"hebrew", "\xd7\x91\xd7\x90\xd7\xa8\xd7\xa6\xd7\x95\xd7\xaa" ); //?????? - hebrew
		_Search(tc,&srch,&a,"japanese", "\xe8\xa6\x8b\xe5\xad\xa6" ); //?? - japanese
		_Search(tc,&srch,&a,"korean", "\xea\xb8\x88" ); //? - korean
		_Search(tc,&srch,&a,"polish", "sp\xc3\xb3\xc5\x82ka"); ;//spólka - polish
		_Search(tc,&srch,&a,"russian", "\xd0\x92\xd0\xb5\xd0\xbb\xd0\xb8\xd0\xba\xd0\xb8\xd0\xb5\x20"); //??????? - russian

        srch.close();*/
        ram.close();
        //_CLDELETE(pram);
 }

	void readBuffered(CuTest* tc, Reader& utf8, Reader& unicode, int readLen){
		utf8.seek(0);
		unicode.seek(0);
		TCHAR* buf1 = _CL_NEWARRAY(TCHAR,readLen);
		TCHAR* buf2 = _CL_NEWARRAY(TCHAR,readLen);
	int p=0;
		int r1,r2;
		int i,j;
		i=0;j=0;
		while(true){
			r1 = utf8.read(buf1,0,readLen);
			r2 = unicode.read(buf2,0,readLen);

			if ( r1 == 0 ){
				break;
			}
			j=0;
			for (i=0;i<readLen;i++){
				if ( i==r1 )
					break;

				if ( j==r2 )
					break;


				if ( buf1[i] != buf2[j] ){
					TCHAR buf[200];
					_sntprintf(buf,200,_T("testReader (read) match failed at position %d"),p);
					CuAssert(tc,buf,false);
				}
				j++;
				p++;
			}
			
		}
		
		_CLDELETE_CARRAY(buf1);
		_CLDELETE_CARRAY(buf2);
	}

/*
  class BufferedReader: public Reader{
	  TCHAR* cachepos;
	  TCHAR* cacheend;
	  TCHAR* cache;
	  TCHAR* cachesoftend;
	  int32_t cachelen;
	  int32_t cachebuffer;
	  int64_t cachefpos;
	  Reader* reader;
	  
	  bool filled;
	  void refill(){
		TCHAR* pos = cache; //where we copy the new data into...
		if ( filled && this->cachebuffer>0 && this->cachepos < cacheend ){
			//there is a remainder of the cache.
			pos = cache+(cacheend-cachepos); //start copying new data after remainder of cache
			STRCPY_TtoT(this->cache,this->cachepos,cacheend-cachepos);
			cachepos = cache;
		}
		filled = true;

		int32_t rd = reader->read(pos,0,cachelen-(pos-cache));
		cacheend=cache+rd;
		cachepos=cache;
		cachefpos+=rd;

		if ( rd == 0 )
			cachesoftend = cacheend; //allow the last remainder to be read with out trying to refill
		else
			cachesoftend = cacheend-this->cachebuffer;
	  }
  public:
	  /**
	  *
	  * @cachelen Length of the cache
	
	  BufferedReader(Reader* reader,int32_t cachelen=64):
		Reader(NULL)
	  {
		this->reader = reader;
		this->cachelen = cachelen;
		this->cache = _CL_NEWARRAY(TCHAR,cachelen);
		this->cachefpos = 0;
		this->cachepos = this->cache;
		this->filled = false;
		this->cachebuffer = 1;
		this->cacheend=this->cache;
		this->cachesoftend = cacheend-this->cachebuffer;
	  }

	  virtual void close(){
		  _CLDELETE_CARRAY(cache);
	  }
	  int32_t read(TCHAR* b, const int64_t start, const int32_t minLength, int32_t maxLength=-1){
		  if ( maxLength < 0 )
			maxLength = minLength;

		  if (!filled )
			refill();

		  int32_t totrd = 0;
		  TCHAR* pb = b;
		  while ( totrd < minLength && cachepos<cacheend ){
			  if ( cachepos >= cachesoftend )
				  refill();
			  if ( cachepos >= cacheend )
				  break;

			  int32_t ln = cachesoftend-cachepos;
			  if ( ln > minLength-totrd )
				  ln = minLength-totrd;
			  STRCPY_TtoT(pb,cachepos,ln);
			  pb+=ln;
			  cachepos+=ln;
			  totrd+=ln;
		  }
		  return totrd;
	  }
	  int64_t available (){
		  return reader->available()+(cachelen-(cachepos-cache));
	  }
	  TCHAR readChar(){
		  if (!filled || ( cachepos >= cachesoftend ) )
			refill();

		  if ( cachepos >= cacheend )
			  return NULL;

		  TCHAR ret = *cachepos;
		  cachepos++;
		  return ret;
	  }
	  TCHAR peek(){
		if ( cachebuffer < 1 )
			_CLTHROWA(CL_ERR_Runtime, "Cannot peek when cachebuffer < 1");

		return *cachepos;
	  }
	int64_t position(){
		int64_t ret = cachefpos + (cachepos-cache);
		return ret;
	}
	void seek(int64_t position){
		if ( position >= cachefpos && position < cachefpos+cachelen ){
			//just reposition in cache
			cachepos = cache+ (position-cachefpos);
		}else{
			reader->seek(position);
			filled=false;
		}
	}
	virtual ~BufferedReader(){
		close();
	}

  };*/

  void doReadChars(CuTest* tc, Reader& utf8, Reader& unicode){
	int p=0;
    TCHAR c1,c2;
	while ( (c1=utf8.readChar()) != 0 ){
		c2 = unicode.readChar();
		if ( c1 != c2 ){
			TCHAR buf[200];
			_sntprintf(buf,200,_T("testReader (readChar) match failed at position %d"),p);
			CuAssert(tc,buf,false);
		}
		p++;
	}
    do{
		c2 = unicode.readChar();
    }while(c2 == 10 || c2 == 13);
	CLUCENE_ASSERT(c2==0); //make sure unicode is finished
  }


 void testReader(CuTest *tc) {
	char* utf8text=CLUCENE_LOCATION "utf8text/french_utf8.txt";
	char* unicodetext=CLUCENE_LOCATION "french_unicode.txt";

	FileReader utf8(utf8text,Reader::ENCODING_UTF8);
	FileReader unicode(unicodetext,Reader::ENCODING_UCS2);

	doReadChars(tc,utf8,unicode);
	//now try reading with read, instead of readChar
	readBuffered(tc,utf8,unicode,3); //test with small buffer
	readBuffered(tc,utf8,unicode,10); //test with word sized buffer
	readBuffered(tc,utf8,unicode,1024); //test with large buffer

	//now try using the BufferedReader...
/*	BufferedReader butf8(&utf8);
	BufferedReader bunicode(&unicode);
	doReadChars(tc,butf8,bunicode);
	readBuffered(tc,butf8,bunicode,3); //test with small buffer
	readBuffered(tc,butf8,bunicode,10); //test with word sized buffer
	readBuffered(tc,butf8,bunicode,1024); //test with large buffer
*/
	utf8.close();
	unicode.close();
 }
#endif
  
void testNotImplemented(CuTest *tc){
	CuNotImpl(tc,_T("UTF8 tests in ascii mode not possible"));
}

CuSuite *testutf8(void)
{
	CuSuite *suite = CuSuiteNew(_T("CLucene UTF8 Test"));

	//todo: temporarily disabled until a solution is found
/*#ifdef _UCS2
    SUITE_ADD_TEST(suite, testReader);
    SUITE_ADD_TEST(suite, testUTF8);
#else*/
    SUITE_ADD_TEST(suite, testNotImplemented);
//#endif
    return suite; 
}
// EOF

