package market.thread;

import java.net.*;
import java.io.*;
import market.*;
import market.util.*;

/**
 * Schedule Netrunner and manage base source 
 * Creation date: (12/16/99 9:21:52 PM)
 * @author: tin
 */
public class Schedule extends Thread {
	// Field
	String lastResult = "";
	long timeSleep; // This is a takt Schedule
	public static SourceList srcList;
	public static LangTable langTable; // This is a table whit Language
	public Graber mGraber[];
	
	public ConfigMarket conf;

	public static SrcElement src;
	
/**
 * Queue between Wr_Processors and Wr_Rw_RateMeter
 */
	public static Queue_rate wr_rw_Count_Stream;
/**
 * Pointer to Wr_Rw_RateMeter
 */
	private static Wr_Rw_RateMeter mRateMeter = null;
	
public Schedule(){
   super("Schedule");
   
//   conf = new ConfigMarket();   
   timeSleep = Const.SCHEDULE_TIME_SLEEP;
   srcList = downloadSrcList();
   langTable = downloadLangTable();
   mGraber = new Graber[ Const.MAX_NETRUNNER ];

// 1. Init Wr_Rw_RateMeter if already not load
	try {
		wr_rw_Count_Stream = new Queue_rate( 30 );
		mRateMeter = new Wr_Rw_RateMeter( wr_rw_Count_Stream );
		wr_rw_Count_Stream.setReaderThread( mRateMeter );
		mRateMeter.setPriority(Const.RATE_METER_PRIORITY);
	} catch (Exception e) {
		ConfigMarket.logWriter.log(getName() + ": Can't create WR_RW_RateMeter!!!", LogPrinter.ERROR);
	}   
 
}
//Methods
public Schedule(long time, SourceList slist, LangTable langlist) {
	super("Schedule");
	
	timeSleep = time;
	srcList = slist;
	langTable = langlist;
	mGraber = new Graber[Const.MAX_NETRUNNER];

	// 1. Init Wr_Rw_RateMeter

	try {
		wr_rw_Count_Stream = new Queue_rate(30);
		mRateMeter = new Wr_Rw_RateMeter(wr_rw_Count_Stream);
		wr_rw_Count_Stream.setReaderThread(mRateMeter);
		mRateMeter.setPriority(Const.RATE_METER_PRIORITY);
	} catch (Exception e) {
		ConfigMarket.logWriter.log(getName() + ": Can't create WR_RW_RateMeter!!!", LogPrinter.ERROR);
	}
}
/**
 * Download lang Table form ResourceServer
 * Creation date: (12/28/99 6:42:48 PM)
 * @return boolean
 */
public static LangTable downloadLangTable() {

	try{ 	
	  URL ServletURL = new URL(ConfigMarket.hostResourceServer +"?"+ Const.REQ_TYPE +"="+ Const.GET_LANG+
		  "&" + Const.MARKET_KEY+"=" + ConfigMarket.marketKey ); 
	  InputStream in = ServletURL.openStream();

	  return ( new LangTable( in ));
	}
	catch(IOException e){
		ConfigMarket.logWriter.log("Schedule: Can't get language table!", LogPrinter.ERROR );
		return null;
	}
}
/**
 * Download lang Table form SourceServer
 * Creation date: (12/28/99 6:42:48 PM)
 * @return SourceList
 */
public static SourceList downloadSrcList() {

	try{  	
	  URL ServletURL = new URL( ConfigMarket.hostSourceServer +"?"+ Const.REQ_TYPE +"="+ Const.GET_SRC+
		  						"&" + Const.MARKET_KEY+"=" + ConfigMarket.marketKey);
	   
	  InputStream in = ServletURL.openStream();

	  return ( new SourceList( in ) );
	}
	catch(IOException e){
		ConfigMarket.logWriter.log("Schedule: Can't get source list!", LogPrinter.ERROR );
		return null;
	}	
}
/**
 * Get lang Table form ResourceServer
 * Creation date: (12/28/99 6:42:48 PM)
 * @return boolean
 */
public static LangTable getLangTable() {
	
	if ( null == langTable ){
		langTable = downloadLangTable();
	}
	
	return (langTable);
}
/**
 * Insert the method's description here.
 * Creation date: (26.2.00 16:37:11)
 * @return java.lang.String
 */
public String getLastOperationResult() {
	return lastResult;
}
/**
 * Get lang Table form ResourceServer
 * Creation date: (12/28/99 6:42:48 PM)
 * @return SourceList
 */
public static SourceList getSrcList() {
	if ( null == srcList ){
		srcList = downloadSrcList();
	}
	
	return ( srcList );
}
/**
 * Get lang Table form ResourceServer
 * Creation date: (12/28/99 6:42:48 PM)
 * @return SourceList
 * @param fileName java.lang.String
 */
public static SourceList getSrcList( String fileName ) {

	try{ 	
	  InputStream in =  new FileInputStream( fileName ) ;

	  return ( new SourceList( in ) );
	}
	catch(IOException e){
		ConfigMarket.logWriter.log("Schedule: Can't open file:"+fileName , LogPrinter.ERROR);
		return null;
	}  
}
/**
 * Check for working Grabbers. Return true if have working Graber.
 * Creation date: (16.5.2000 “. 19:48:28)
 * @return boolean
 */
public boolean isGrabberWork() {
	int graber;
	
	for ( graber = 0; graber < Const.MAX_NETRUNNER; graber++) {
		if ( (mGraber[graber] != null) && ( mGraber[graber].isWorking() )) {
			return true;
		}		
	}

	return false;
		
}
/**
 * For test 
 * Creation date: (1/9/00 6:26:16 PM)
 * @param args java.lang.String[]
 */
public static void main(String[] args) {
	Runtime myRuntime = Runtime.getRuntime();
   	myRuntime.traceInstructions( true ); 
   	myRuntime.traceMethodCalls( true ); 

	// 3. Create instance of ScheduleThread
	System.out.println(" Create Scedule... ");

	ConfigMarket.init( "h:\\testmarket\\cfg\\market.cfg" );
//	ConfigMarket.init( "k:\\market\\market.cfg" );
		
	Schedule mSchedule = new Schedule();

	ConfigMarket.mDocsCacher.loadCache();
	
	// 4. Load Langage Table
	mSchedule.getLangTable();
	if ( null != mSchedule.langTable ) mSchedule.langTable.print();

	// 5. Load Source List
	mSchedule.getSrcList(); //  srcFile 
	if ( null != mSchedule.srcList ){
		mSchedule.srcList.sort();
		mSchedule.srcList.print();
		mSchedule.srcList.printToday();
	}	
//	scdEditURL( long srcKey, int timeBase, int frequence, 
//							int keepInPath, int keepInDomain, int grabLevels)

	mSchedule.scdEditURL( (long)223, 200, 1, 0, 0, 1, "Mozilla 6.0");
	mSchedule.scdActivateURL( (long)223, true );
//	scdSubscribeURL(String srcString, int langKey, int timeBase, int frequence, 
//			int keepInPath, int keepInDomain, int grabLevels, String userAgent) 
	mSchedule.scdSubscribeURL("http://www.market2.esof/index.html/", 1, 1200 , 2, 1, 0, 0,"Java.1.1.8");
		
	int index = mSchedule.srcList.findSrc( (long)679 );
	mSchedule.srcList.srcBundle[index].setActive(true);
		
	// 6. Start mSchedule
	System.out.println("Start Schedule ");
	mSchedule.startGraber( mSchedule.srcList.srcBundle[index] );
//	mSchedule.start();
//	mSchedule.mRateMeter.stop();
//	mSchedule.startGraber( mSchedule.srcList.srcBundle[index] );

	mSchedule.stopAllGraber();
	
}
public void run(){
	
  srcList.print();

  src = srcList.getNextToStart(); 

  while ( true ){
	ConfigMarket.logWriter.log("\nSchedule weak up", LogPrinter.DEBUG_2);
	ConfigMarket.logWriter.log("Check is have src for start curSrc= "+srcList.curElm, LogPrinter.DEBUG_2); 

	if ( srcList.StartNow( src ) ) {
	  yield();
	  
// Start Netrunner
 	  startGraber( src );	
	  ConfigMarket.logWriter.log("Done", LogPrinter.DEBUG_2);
	  yield();
	  src = srcList.getNextToStart();
	} 

	ConfigMarket.logWriter.log("Schedule going to sleep", LogPrinter.DEBUG_2);
	ConfigMarket.logWriter.flush(); 
	try{
	 sleep( timeSleep );
	 yield();
	}
	catch (InterruptedException e){
	}
  }
 
}
/**
 * Activate baseSrc (URL) on SrcServer and market SrcList
 * Creation date: (07/13/00 4:04:43 PM)
 * @return boolean
 * @param srcKey long 
 * @param active boolean
 */
public boolean scdActivateURL(long srcKey, boolean activate) {
	String sActivate = (activate) ? "activate" : "deactivate";
	synchronized (srcList) {
		int index = srcList.findSrc(srcKey);
		if (-1 == index) {
			lastResult = "Can't find URL with srcKey =" + srcKey + " !";
			return false;
		}
		StringBuffer ret_res = new StringBuffer(Const.MAX_LEN_KEY);
		try {
			URL ServletURL = new URL(ConfigMarket.hostSourceServer + "?" + Const.REQ_TYPE + "=" + Const.ACTIV_SRC 
				+ "&" + Const.MARKET_KEY + "=" + ConfigMarket.marketKey 
				+ "&" + Const.BASE_SRC_KEY + "=" + srcKey 
				+ "&" + Const.ACTIVE + "=" + ((activate) ? 1 : 0) );
			InputStream in = ServletURL.openStream();
			int b;
			while ((b = in.read()) != -1) {
				ret_res.append((char) b);
			}
			in.close();
			String temp = ret_res.toString().trim() ;
			if ( temp.equalsIgnoreCase("true") ) {
				SrcElement srcElm = srcList.srcBundle[index];
				synchronized (srcElm) {
					srcElm.active = activate;
				}
				lastResult = "URL was " + sActivate + ".";
				return true;
			}
			lastResult = "URL " + sActivate + " deny.";
			return false;
		} catch (Exception e) {
			ConfigMarket.logWriter.log("Schedule: Can't " + sActivate + " URL!:" + e.toString() , LogPrinter.ERROR);
			lastResult = "Can't connect to system for URL " + sActivate;
			return false;
		}
	}
}
/**
 * Delete baseSrc (URL) on SourceServer and market SrcList
 * Creation date: (12/29/99 4:04:43 PM)
 * @return boolean ( true for success )
 * @param baseSrcKey long
 */
public boolean scdDeleteURL( long baseSrcKey ) {
	
	StringBuffer ret_srcKey = new StringBuffer( Const.MAX_LEN_KEY );
	boolean res;

	try{
		
	  URL ServletURL = new URL(ConfigMarket.hostSourceServer +"?"+ Const.REQ_TYPE +"="+ Const.DEL_SRC+ 
		  "&" + Const.BASE_SRC_KEY +"="+ baseSrcKey+ 
		  "&" + Const.MARKET_KEY +"="+ ConfigMarket.marketKey); 

	  InputStream in = ServletURL.openStream();
	  
	  int b; 
	
 	  while ((b =in.read())!= -1){ 
	 	  ret_srcKey.append((char)b);  
	  } 
 
	  res = ret_srcKey.toString().equalsIgnoreCase("true");

//	  SrcElement srcElm = new SrcElement( srcString, srcKey, langKey, timeBase, 
//										frequence, (keepInPath == 1), grabLevel);
	  if ( res ){	  	
 	  	res = srcList.delElm( baseSrcKey );
  		lastResult = "URL deleted.";
	  }
	  else{
  		ConfigMarket.logWriter.log("Schedule: Can't delete URL!", LogPrinter.ERROR);
  		lastResult = "Can't delete URL!";
	  }
	  	
	  return res;
	}
	catch( Exception e ){
		ConfigMarket.logWriter.log("Schedule: Can't delete URL!", LogPrinter.ERROR);	
  		lastResult = "Can't delete URL!";
		return false;
	}
	
}
/**
 * Edit baseSrc (URL) on SrcServer and market SrcList
 * Creation date: (12/29/99 4:04:43 PM)
 * @return boolean
 * @param srcKey long 
 * @param timeBase int
 * @param frequence int
 * @param keepInPath int
 * @param keepInDomain int
 * @param grabLevel int
 * @param userAgent String
 */
public boolean scdEditURL( long srcKey, int timeBase, int frequence, 
							int keepInPath, int keepInDomain, int grabLevels, String userAgent ) {

	int index = srcList.findSrc( srcKey );
	
	if ( -1 == index ){
  		lastResult = "Can't find URL with srcKey ="+ srcKey +" !";
		return false;
	}							
	StringBuffer ret_res = new StringBuffer( Const.MAX_LEN_KEY );
	String encoded_userAgent = URLEncoder.encode( userAgent );	


	try{
		
	  URL ServletURL = new URL(ConfigMarket.hostSourceServer +"?"+ Const.REQ_TYPE +"="+ Const.EDIT_SRC+ 
		  "&" + Const.MARKET_KEY +"="+ ConfigMarket.marketKey+ 
		  "&" + Const.BASE_SRC_KEY +"="+ srcKey + 
		  "&" + Const.TIME_BASE +"="+ timeBase + "&" + Const.FREQ +"="+ frequence + 
		  "&" + Const.KEEP_IN_PATH +"="+ keepInPath + 
		  "&" + Const.KEEP_IN_DOMAIN +"="+ keepInDomain+
		  "&" + Const.GRAB_LEVEL +"="+ grabLevels+
		  "&" + Const.USER_AGENT +"="+ encoded_userAgent ); 

	  InputStream in = ServletURL.openStream();
	  
	  int b; 
	
 	  while ((b =in.read())!= -1){ 
	 	  ret_res.append((char)b);  
	  } 

 	  in.close();
 	  
	  if ( ret_res.toString().equalsIgnoreCase("true")){
		  
	  	SrcElement srcElm = srcList.srcBundle[index];
	  	synchronized (srcElm){
		  	srcElm.timeBase = timeBase;
		  	srcElm.frequence = frequence; 
			srcElm.keepInPath =	(keepInPath == 1);
			srcElm.keepInDomain =(keepInDomain == 1);
			srcElm.grabLevels = (byte)grabLevels;
			srcElm.userAgent = userAgent;
	  	}
	  	
	  	srcList.sort();
	  	
  		lastResult = "URL was edited.";
	  	return true;
	  }
	  
	  lastResult = "URL edit deny.";
	  return false;	
	}
	catch( Exception e ){
		ConfigMarket.logWriter.log("Schedule: Can't edit URL!", LogPrinter.ERROR);	
 	  	lastResult = "Can't connect to system for URL editing.";
		return false;
	}
	
}
/**
 * Registrate new baseSrc (URL) on ResourceServer and market SrcList
 * Creation date: (12/29/99 4:04:43 PM)
 * @return boolean ( true for success )
 * @param srcString java.lang.String
 * @param lang java.lang.String
 * @param timeBase int
 * @param frequence int
 * @param keepInPath int
 * @param grabLevel int
 * @param userAgent String 
 */
public boolean scdSubscribeURL(String srcString, int langKey, int timeBase, int frequence, 
			int keepInPath, int keepInDomain, int grabLevels, String userAgent) {
	StringBuffer ret_srcKey = new StringBuffer(Const.MAX_LEN_KEY);
	String encoded_srcString = URLEncoder.encode( srcString );
	String encoded_userAgent = URLEncoder.encode( userAgent );
	
	long srcKey;
	synchronized (srcList) {
		try {
			URL ServletURL = new URL(ConfigMarket.hostSourceServer + "?" + 
				Const.REQ_TYPE + "=" + Const.REG_SRC + "&" + 
				Const.SRC_STRING + "=" + encoded_srcString + "&" + 
				Const.LANG_KEY + "=" + langKey + "&" + 
				Const.MARKET_KEY + "=" + ConfigMarket.marketKey + "&" + 
				Const.TIME_BASE + "=" + timeBase + "&" + 
				Const.FREQ + "=" + frequence + "&" + 
				Const.KEEP_IN_PATH + "=" + keepInPath + "&" + 
				Const.KEEP_IN_DOMAIN + "=" + keepInDomain + "&" + 
				Const.USER_AGENT + "=" + encoded_userAgent + "&" + 
				Const.GRAB_LEVEL + "=" + grabLevels);
			InputStream in = ServletURL.openStream();
			int b;
			while ((b = in.read()) != -1) {
				ret_srcKey.append((char) b);
			}
			srcKey = Long.valueOf(ret_srcKey.toString()).longValue();
			if (srcKey > 0) {
				// Ok. URL is registred 
				SrcElement srcElm = new SrcElement( srcString, srcKey, langKey, timeBase, 
					frequence, (keepInPath == 1), (keepInDomain == 1), grabLevels, userAgent);
				if (!srcList.insertElm(srcElm)) {
					lastResult = "Can't add URL in local list.";
					if (srcList.lastElm >= Const.MAX_NUM_SRC) {
						lastResult += "You can't add more URL!( maxURL=" + Const.MAX_NUM_SRC + " )";
					}
					return false;
				}
				lastResult = "URL added.";
			}
			return true;
		} catch (Exception e) {
			ConfigMarket.logWriter.log("Schedule: Can't subscribe URL!", LogPrinter.ERROR);
			lastResult = "Can't connect to system for adding URL!";
			return false;
		}
	}
}
/**
 * Start Graber whit Source in src element
 * Creation date: (1/24/00 6:05:56 PM)
 * @param src market.util.SrcElement
 */
public void startGraber(SrcElement src) {
	
	int firstFreeGraber;
	boolean getFreeGraber = true;
	
	do {
		for (firstFreeGraber = 0; firstFreeGraber < Const.MAX_NETRUNNER; firstFreeGraber++) {
			if ((mGraber[firstFreeGraber] == null) || ( !mGraber[firstFreeGraber].isWorking() )  ) {
				break;
			}
		}
		if (firstFreeGraber >= Const.MAX_NETRUNNER) {
			ConfigMarket.logWriter.log("Schedule: Wait to finish own Graber...", LogPrinter.DEBUG );
			getFreeGraber = false;
			try{
				Thread.sleep( 100 );
			}catch( InterruptedException e ){};
		}
		else
			getFreeGraber = true;

	} while (!getFreeGraber);
	
	ConfigMarket.logWriter.log("Schedule: Starting Graber...", LogPrinter.INFO );
	mGraber[firstFreeGraber] = null;
	mGraber[firstFreeGraber] = new Graber(firstFreeGraber, src, langTable, mRateMeter);
	try {
		mGraber[firstFreeGraber].setDaemon( true ); 
		mGraber[firstFreeGraber].init(); // Init Netrunner
	} catch (Exception e) {
		ConfigMarket.logWriter.log("Can't init Graber!!!", LogPrinter.ERROR );
		return;
	}
	mGraber[firstFreeGraber].start();
	ConfigMarket.logWriter.log("Schedule: Starting Graber...Done", LogPrinter.INFO );
}
/**
 * Stop All Netrunners.
 * Creation date: (1/24/00 6:05:56 PM)
 */
public void stopAllGraber() {
	
	int graber;
	
	ConfigMarket.logWriter.log("Schedule: Stoping All Graber...", LogPrinter.INFO );
	
	mRateMeter.resume();
	mRateMeter.stop();
	
	for ( graber = 0; graber < Const.MAX_NETRUNNER; graber++) {
		if ( (mGraber[graber] != null) ) {
			mGraber[graber].baseSrcElem.processing = false;
			mGraber[graber].stop();
			mGraber[graber] = null;
		}
		
	}

	
	ConfigMarket.logWriter.log("Schedule: Stoping All Graber...Done", LogPrinter.INFO );
}
}

