package tts.filetospeech;

import java.io.*;
import java.util.*;
import android.util.Log;
import java.util.concurrent.locks.*;
import android.speech.tts.*;
import android.speech.tts.TextToSpeech.OnInitListener;

public class Speech  implements Runnable
{
	TextToSpeech tts;
	boolean firstTime = true;
	HashMap<String, String> hashMap;
	InputStream is = null;
	BufferedReader reader = null;
	final Lock mutex = new ReentrantLock();
	final Condition textSpoken = mutex.newCondition();
	final Lock mutex1 = new ReentrantLock();
	final Condition pauseCond = mutex1.newCondition();
	int count = 0;
	int position = 0; 
	final int LEN = 20;
	String buffer[] = new String[LEN];
	boolean pausing = false;
	boolean starting = true;
	boolean resuming = false;
	
	public Speech ( TextToSpeech tts0, InputStream is0 )
	{
		tts = tts0;
		is = is0;
		Log.v ("Speech", "Constructor");
	}
	
	@Override
	public void run() {
      try {
    	Log.v ("Speech", "run");
		speak();
	  } catch (InterruptedException e) {
				e.printStackTrace();
	  }		
		
	}

	private void speak() throws InterruptedException {    	 
      String str = null;
      if ( firstTime ){
    	System.out.println ("Thread Speech");  
        String keyText = "Text Spoken ID";
        hashMap = new HashMap();
        hashMap.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, keyText);
        MyUtteranceProgressListener listener = new MyUtteranceProgressListener();
        tts.setOnUtteranceProgressListener ( listener );
        firstTime = false;
      }
      try {
       if ( reader == null  ) 
 		  reader = new BufferedReader(new InputStreamReader(is));
 	   while ((str = reader.readLine()) != null) {
 		   mutex1.lock();
 		   while ( pausing )
             pauseCond.await();
 		   mutex1.unlock();
 		   mutex.lock();
 		   count++;
 		   if ( starting ){
 			   tts.speak( str, TextToSpeech.QUEUE_FLUSH, hashMap );
 			   starting = false;
 		   } else {
 			   if ( resuming ) {
 		   
 			     // copy buffer string back
 				 int j =  position - 1;
 				 if ( j < 0 ) j = j + LEN;
 			     for ( int i = 1; i < count; i++){
 			    	 if ( i == 1 )
 			    		tts.speak( buffer[j], TextToSpeech.QUEUE_FLUSH, hashMap );
 			    	 else
 			    		tts.speak( buffer[j], TextToSpeech.QUEUE_ADD, hashMap );
 			    	 j = ( j + 1) % LEN;
 			     }
 		       }
 			  tts.speak( str, TextToSpeech.QUEUE_ADD, hashMap );
 			 }
 		   while ( count > LEN )
 		       textSpoken.await();   // Condition wait
 		  mutex.unlock();
 		  String temp = Integer.toString( count );
 		  
 		  Log.v("speak count", temp );
 		   buffer[position] = str;
 		   position++;
 		   if ( position == LEN )
 		    	 position = 0;
 		  
 		 }
      }  catch(IOException e) {
             Log.e("speak", e.getMessage());
      }   
   }
	
    public void onUtteranceCompleted ( String utteranceId ) {
    	System.out.println (".."+ utteranceId );
        if ( utteranceId.equals("Text Spoken ID")) { 
            System.out.println ("..Text Spoken!" );
            mutex.lock();
            count--;
            textSpoken.signal();
            mutex.unlock();
        } 
     }
    
    class MyUtteranceProgressListener extends UtteranceProgressListener
    {
        @Override
        public void onDone(String utteranceId)
        {
           onUtteranceCompleted ( utteranceId );
        }

        @Override
        public void onError(String utteranceId)
        {
        }

		@Override
		public void onStart(String arg0) {
			// TODO Auto-generated method stub
			
		}

     }
    
    public void speechPause()
    {
    	if ( pausing ) return;  // engine already stopped
    	
    	mutex1.lock();
    	pausing = true;
    	mutex1.unlock();
    	tts.stop();     // stop engine, clears utterance queue
    	Log.v ("Speech", "pause");
    }
    
    public void speechResume ()
    {
    	if ( !pausing ) return;
    	
    	mutex1.lock();
    	pausing = false;
    	resuming = true;
    	pauseCond.signal();   // Wake up the waiting method
    	mutex1.unlock();
    	Log.v ("Speech", "resume");
    }
}
