package com.gx.obe.management.thread;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.gx.obe.business.entity.ExpertLibrary;
import com.gx.obe.business.http.HttpUtils;
import com.gx.obe.components.core.enumeration.CommonEnum;
import com.gx.obe.config.ConfigConstants;
import com.gx.obe.config.utils.PropertiesUtils;
import com.gx.obe.thread.DownloadMonitorsThread;
import com.gx.obe.thread.DownloadWorkersThread;
import com.gx.obe.web.entity.TransactionServer;
import com.gx.obe.web.entity.tender.TenderProjectEntity;
import com.gx.obe.web.service.TenderProjectService;

/**
 * @Description: 自动下载
 * @author chenxw
 */
public class AutomaticDownloader implements Runnable {
	
	private static final Map<Key, Thread> map = new HashMap<Key, Thread>();
	private static final String isUseAutomaticDownload = PropertiesUtils.getProperty(ConfigConstants.IS_USE_AUTOMATIC_DOWNLOAD, CommonEnum.NO);
	private static final TenderProjectService tenderProjectService = new TenderProjectService();
	
	private static ExecutorService executorService;
	
	private final Key key;
	
	private AutomaticDownloader(Key key) {
		this.key = key;
	}
	
	/**
	 * @Description: 启动
	 * @author chenxw
	 * @param tenderId
	 * @throws Exception
	 */
	public static void start(String tenderId){
		for (DownType downType : DownType.values()) {
			try {
				start(tenderId, downType);
			} catch (Exception e) {
			}
		}
	}
	
	/**
	 * @Description: 启动
	 * @author chenxw
	 * @param tenderId
	 * @param downType
	 * @throws Exception
	 */
	public static void start(String tenderId, DownType downType) throws Exception {
		if (!CommonEnum.YES.equals(isUseAutomaticDownload)) {
			return;
		}
		if (null == tenderId) throw new Exception("tenderId is null");
		if (null == downType) throw new Exception("downType is null");
		Key key = new Key(tenderId, downType);
		if (map.containsKey(key)) {
			return;
		}
		Thread thread = new Thread(new AutomaticDownloader(key));
		map.put(key, thread);
		if (null == executorService) {
			executorService = Executors.newFixedThreadPool(5);
		}
		executorService.submit(thread);
	}
	
	/**
	 * @Description: 清空当前所有线程
	 * @author chenxw
	 */
	public static void shutdownNow() {
		map.clear();
		if (null != executorService) {
			executorService.shutdownNow();
			executorService = null;
		}
	}
	
	public void run() {
		TenderProjectEntity tenderProject = tenderProjectService.getById(key.tenderId);
		switch (key.downType) {
			case expert:
				downloadExpert(tenderProject);
				break;
			case worker:
				downloadWorker(tenderProject);
				break;
			case monitor:
				downloadMonitor(tenderProject);
				break;
		}
		map.remove(key);
	}
	
	/**
	 * @Description: 下载专家
	 * @author chenxw
	 * @param tenderProject
	 */
	private void downloadExpert(TenderProjectEntity tenderProject) {
		TransactionServer transactionServer = HttpUtils.getTransactionServer(tenderProject.getTransactionServerId());
		if (null == transactionServer) {
			return;
		}
		ExpertLibrary expertLibrary = new ExpertLibrary();
		expertLibrary.setExpertLibAddress(transactionServer.getServerAddress());
		DownloadExpertThread thread = new DownloadExpertThread(tenderProject, expertLibrary.getExpertLibAddress(), null);
		thread.start();
		try {
			thread.join();
		} catch (InterruptedException e) {}
	}
	
	/**
	 * @Description: 下载工作人员
	 * @author chenxw
	 * @param tenderProject
	 */
	private void downloadWorker(TenderProjectEntity tenderProject) {
		DownloadWorkersThread workersThread = new DownloadWorkersThread(tenderProject, null);
		workersThread.start();
		workersThread.join();
	}
	
	/**
	 * @Description: 下载监督人员
	 * @author chenxw
	 * @param tenderProject
	 */
	private void downloadMonitor(TenderProjectEntity tenderProject) {
		DownloadMonitorsThread monitorsThread = new DownloadMonitorsThread(tenderProject, null);
		monitorsThread.start();
		monitorsThread.join();
	}
	
	public enum DownType {
		expert, worker, monitor
	}
	
	static class Key {
		String tenderId;
		DownType downType;
		
		public Key(String tenderId, DownType downType) {
			this.tenderId = tenderId;
			this.downType = downType;
		}
		
		public int hashCode() {
			return tenderId.hashCode() + downType.hashCode();
		}
		
		public boolean equals(Object obj) {
			Key key = (Key) obj;
			return tenderId.equals(key.tenderId) && downType.equals(key.downType);
		}
		
	}
	
}
