package net.kldp.logviewer.work;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import net.kldp.logviewer.View;
import net.kldp.logviewer.common.log.LogViews;
import net.kldp.logviewer.model.LogViewerEntry;

import org.apache.log4j.Logger;

/**
 * 파일을 주기적으로 읽어주는 Thread이다.
 * 
 * 주의) 아직은 문제가 있는 부분이 존재하고 보완할 여지가 있다.
 * 
 * @author hangumkj
 */
public class WorkerFileTail extends Thread implements Tail {
	
	private static final Logger logger = LogViews.getLogger(WorkerFileTail.class);
	
	View view = null;
	LogViewerEntry viewEntry = null;
	private volatile boolean shutdownThread = false;
	private volatile boolean sleepThread = false;
    
	public WorkerFileTail(LogViewerEntry viewEntry, View tailMe) {
		if(logger.isDebugEnabled()) { 
			logger.debug("WorkerFileTail Started......[name]" + viewEntry.getName());
		}
		this.view = tailMe;
		
		outputLog(viewEntry.getRealPath() + "의 보기를 시작합니다.\r\n");		
		this.viewEntry = viewEntry;
	}
	
	/**
	 * 잠시중단
	 */
	public void sleep() {
		sleepThread = true;
		
		try {
			Thread.currentThread().wait();
		} catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 다시시작
	 */
	public void reStart() {
		sleepThread = false;		
		
		Thread.currentThread().notify();
	}
	
	/**
	 * 쓰레드 종료
	 *
	 */
	public void shutdown() {
		shutdownThread = true;
		interrupt();
	}
	
	public void run() {
		BufferedInputStream bis = null;
		
		try {
			int length = -1;
			
			boolean findFile = false;
			try {
				bis = new BufferedInputStream(new FileInputStream(viewEntry.getRealPath()), 1024);			
				
			    // 파일의 엔드포인트로 이동한다.
			    bis.skip(new File(viewEntry.getRealPath()).length());
			    
			    findFile = true;
			} catch(IOException ioe) {
				findFile = false;
				outputLog(ioe.getMessage());
			}
			
		    while(!shutdownThread) {
		    	
		    	try {
		    		// thread의 wait 상태이다.
					if(sleepThread) {
						
					// working 상태
					} else {
						// 파일이 발견되지 않으면 파일을 계속 찾는다.
				    	if(!findFile) {
					    	try {
								bis = new BufferedInputStream(new FileInputStream(viewEntry.getRealPath()), 1024);			
								
							    length = bis.available();     
					    		if (length == -1) throw new IOException("파일이 존재 하지 않습니다. 확인해 주십시오.");        
					    
					    		if (length > 0) {		        
					    			byte[] data = new byte[length];
					    			
					    			if (bis.read(data, 0, length) != -1) outputLog(data);
					    		}
							    
							    findFile = true;
							} catch(IOException ioe) {
								findFile = false;
								outputLog(ioe.getMessage());
							}
						// 파일을 찾았으면...
				    	} else {
				    		length = bis.available();     
				    		if (length == -1) throw new IOException("파일이 존재 하지 않습니다. 확인해 주십시오.");        
				    
				    		if (length > 0) {		        
				    			byte[] data = new byte[length];
				    			
				    			if (bis.read(data, 0, length) != -1) outputLog(data);
				    		}
				    			
				    	} // 파일 발견됐는지 검사 if			    		
			       
			    		// 원하는 시간만큼 딜레이 된다. 
			    		try {
			    			Thread.sleep(viewEntry.getDelaySecond() * 1000);
			    		} catch(InterruptedException e) {}
					}
		    	} catch (Exception e) {
		    		e.printStackTrace();
		    		outputLog(e.getMessage());
		    	}
		    }
		} catch (Exception e) {
			e.printStackTrace();
			
			outputLog(e.getMessage());					
		} finally {
			try { bis.close(); } catch(IOException ioe){}
			logger.debug("###[WorkerFileTail가 쓰레드 작업종료] ");// + Thread.currentThread().getId());
		}
	}

	/**
	 * 화면에 출력하기 위해 work에게 던져주는 역활을 한다.
	 * 
	 * @param data
	 */
	protected void outputLog(byte[] data) {
		if(!new String(data).equals("")) view.fileAddData(new String(data));
	}
	
	protected void outputLog(String data) {
		if(!"".equals(data)) view.fileAddData(data);
	}
}
