package com.uas.search.console.b2b.support;

import java.sql.SQLRecoverableException;
import java.util.HashSet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.uas.search.util.CollectionUtils;

import com.alibaba.druid.pool.DruidDataSource;
import com.uas.search.b2b.model.SPage;
import com.uas.search.console.b2b.DruidDBConfiguration;
import com.uas.search.console.b2b.util.ContextUtils;
import com.uas.search.console.b2b.jms.AQListener;
import com.uas.search.console.b2b.jms.LuceneQueueMessage;
import com.uas.search.console.b2b.jms.LuceneQueueMessageDao;
import com.uas.search.console.b2b.schedule.model.TaskInformation;
import com.uas.search.console.b2b.schedule.service.Executable;
import com.uas.search.console.b2b.schedule.service.TaskService;
import com.uas.search.console.b2b.util.SearchConstants.DataSourceQualifier;

/**
 * 创建定时任务，监控实时更新异常情况
 * 
 * @author sunyj
 * @since 2016年12月19日 下午3:40:03
 */
public class RealTimeUpdateMonitor {

	private TaskService taskService = ContextUtils.getBean(TaskService.class);

	private AQListener aqListener = ContextUtils.getBean(AQListener.class);

	private DataSourceQualifier dataSourceQualifier;

	/**
	 * 上次查询时最旧的消息
	 */
	private LuceneQueueMessage oldestMessage;

	/**
	 * 第一次执行的延迟时间间隔为1秒
	 */
	private static final long INITIAL_DELAY = 1000;

	/**
	 * 两次任务之间的等待时间间隔为5分钟
	 */
	private static final long PERIOD = 5 * 60 * 1000;

	private Logger logger = LoggerFactory.getLogger(getClass());

	public RealTimeUpdateMonitor(DataSourceQualifier dataSourceQualifier) {
		this.dataSourceQualifier = dataSourceQualifier;
	}

	public TaskInformation newTask() {
		String title = "监控实时更新异常情况：" + dataSourceQualifier.getQualifier();
		Executable command = new Executable() {
			@Override
			public String execute() {
				// 如果实时更新未正常运行，发送警告短信并自动重启实时更新服务
				try {
					if (!workWell()) {
						HashSet<DataSourceQualifier> dataSourceQualifiers = new HashSet<>();
						dataSourceQualifiers.add(dataSourceQualifier);
						logger.error("实时更新未正常运行：" + dataSourceQualifier.getQualifier());
						logger.info("发送警告短信...");
						logger.info("重启实时更新服务：" + dataSourceQualifier.getQualifier());
						if (aqListener.isRunning(dataSourceQualifier)) {
							aqListener.stop(dataSourceQualifiers);
						}
						aqListener.start(dataSourceQualifiers, null);
						return "异常";
					}
				} catch (SQLRecoverableException e) {
					logger.error("", e);
					return "数据库连接错误";
				}
				return "正常";
			}
		};
		TaskInformation taskInformation = new TaskInformation(title, command, INITIAL_DELAY, PERIOD);
		taskService.newTask(taskInformation);
		return taskInformation;
	}

	/**
	 * 实时更新服务是否运行良好
	 * 
	 * @return true 如果运行良好
	 * @throws SQLRecoverableException
	 */
	private boolean workWell() throws SQLRecoverableException {
		DruidDataSource dataSource = DruidDBConfiguration.getDataSource(dataSourceQualifier);
		SPage<LuceneQueueMessage> sPage = new LuceneQueueMessageDao(dataSource).findAll(1, 1, null);
		// 如果消息队列中没有消息，说明没有等待更新的消息
		if (CollectionUtils.isEmpty(sPage.getContent())) {
			return true;
		}
		LuceneQueueMessage luceneQueueMessage = CollectionUtils.isEmpty(sPage.getContent()) ? null
				: sPage.getContent().get(0);
		// 比较上次与本次查询的最旧的消息，如果两者相同，说明实时更新服务出现了问题
		if (oldestMessage != null && oldestMessage.equals(luceneQueueMessage)) {
			return false;
		} else {
			oldestMessage = luceneQueueMessage;
			return true;
		}
	}

}
