package oracle.search.plugin.genie;

import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.util.Date;

import oracle.search.sdk.crawler.CrawlerPlugin;
import oracle.search.sdk.crawler.CrawlingThreadService;
import oracle.search.sdk.crawler.DataSourceService;
import oracle.search.sdk.crawler.DocumentAcl;
import oracle.search.sdk.crawler.DocumentContainer;
import oracle.search.sdk.crawler.DocumentMetadata;
import oracle.search.sdk.crawler.GeneralService;
import oracle.search.sdk.crawler.Logger;
import oracle.search.sdk.crawler.ParameterValues;
import oracle.search.sdk.crawler.PluginException;
import oracle.search.sdk.crawler.ProcessingException;
import oracle.search.sdk.crawler.QueueService;

public class GenieCrawlerPlugin implements CrawlerPlugin {
	
	private boolean m_abortCrawl = false;
	private boolean m_incremental = false;
	
	private String m_paramValue1 = null;
	private String m_paramValue2 = null;
	private String m_paramValue3 = null;
	
	private GeneralService m_generalService = null;
	private QueueService m_queueService = null;
	private DataSourceService m_dataSourceService = null;
	private boolean m_forceRecrawl = false;
	private Date m_lastCrawlTime = null;
	private CrawlingThreadService m_cts = null;
	private Logger m_log = null;
	
	public GenieCrawlerPlugin(GeneralService generalMgr, CrawlingThreadService cts, 
			boolean forceRecrawl, Date lastCrawlTime,
			String paramValue1, String paramValue2, String paramValue3){
		this.m_generalService = generalMgr;
		this.m_queueService = generalMgr.getQueueService();
		this.m_dataSourceService = generalMgr.getDataSourceService();
		this.m_cts = cts;
		this.m_lastCrawlTime = lastCrawlTime;
		this.m_forceRecrawl = forceRecrawl;
		this.m_paramValue1 = paramValue1;
		this.m_paramValue2 = paramValue2;
		this.m_paramValue3 = paramValue3;
		this.m_log = generalMgr.getLoggingService();
	}

	public void crawl() throws PluginException {
		if (!m_forceRecrawl && m_lastCrawlTime!=null) 
			m_incremental = true;
		
		connectToRepository();
		
		while(!m_abortCrawl){
			
			DocumentMetadata newMetadata = m_queueService.getNextItem();
			if(newMetadata!=null){
				String url = newMetadata.getDisplayURL();
				
				try {
					getMetaData(newMetadata, url);
				} catch (ProcessingException e) {
					m_log.error(e.toString(), this);			
				}
				
				if (m_incremental){
					
					DocumentMetadata perviousMetadata = m_dataSourceService.getDocumentAttributes(url);
					if (!isDocumentModified(newMetadata,perviousMetadata)){
						try {
							m_cts.markStatusNotChanged(newMetadata);
						} catch (ProcessingException e) {
							m_log.error(e.toString(), this);
						}
						continue;
					}
					
					DocumentContainer dc = createDocumentContainer(newMetadata,url);
					
					submit(dc,DocumentContainer.STATUS_OK_FOR_INDEX);
				}
			}
		}
	}

	private void connectToRepository() {
		
	}

	private void submit(DocumentContainer dc, int statusCode) {
		try{
			dc.setDocumentStatus(statusCode);
			m_cts.submitForProcessing(dc);
		}
		catch (ProcessingException e){
			m_log.error(e.toString(), this);
		}
	}

	private DocumentContainer createDocumentContainer(DocumentMetadata newMetadata,
			String url) {
		
		DocumentContainer dc = m_generalService.newDocumentContainer();
		
		Object content = getContent(url);
		if (content instanceof InputStream) 
			dc.setDocument((InputStream)content);
		else if (content instanceof String) 
			dc.setDocument(new StringReader((String)content));
		
		dc.setMetadata(newMetadata);
		return dc;
	}

	private Object getContent(String url) {
		
		String content = "Content fetched from the repository for the given url";
		return content;
	}

	private boolean isDocumentModified(DocumentMetadata newMetadata,
			DocumentMetadata perviousMetadata) {
		

		
		boolean isACLModified = false;

		
		Date previousLMD = perviousMetadata.getLastModifiedDate();
		boolean isDocumentModified = (previousLMD == null) || (previousLMD.before(newMetadata.getLastModifiedDate()));

		return isACLModified || isDocumentModified;
	}

	private void getMetaData(DocumentMetadata newMetadata, String url) throws ProcessingException{
		
		String author = "fetch author from repository for given url";
		newMetadata.setAttributes("Author", new String[]{author});
		
		Date lmd = new Date();   
		newMetadata.setLastModifiedDate(lmd);
		
		
		String subject = "fetch Subject attribute value from repository for the given url to set as title attribute value";
		newMetadata.setAttributes("Title", new String[]{subject});
		
		
		DocumentAcl docAcl = m_generalService.newDocumentAcl();
		String aceName = "ace for the given url"; 
		String authenticationAttr = "USER_NAME"; 
		
		
		docAcl.addPrincipal(aceName, authenticationAttr, DocumentAcl.USER);
		
		docAcl.addDenyPrincipal(aceName, authenticationAttr, DocumentAcl.USER);
		
		docAcl.addPrincipal(aceName, authenticationAttr, DocumentAcl.GROUP);
		
		docAcl.addDenyPrincipal(aceName, authenticationAttr, DocumentAcl.GROUP);
		
		newMetadata.setACLInfo(docAcl);
	}

	public void init() throws PluginException {
		
		m_abortCrawl = false;
	}

	public void stopCrawling() throws PluginException {
		
		m_abortCrawl = true;		
	}

}

