package com.gyee.frame.util.mongodb;


import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.Lists;
import com.gyee.frame.common.spring.InitialRunner;
import com.gyee.frame.model.auto.RMConfig;
import com.gyee.frame.model.custom.PointData;
import com.gyee.frame.util.StringUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.*;

/**
 */
public class HistorySnapUtil {



	private String mongodb_c = "C";
	private String mongodb_db = "H";
	private String mongodb_p = "K";
	private String mongodb_ls = "M";
	private String mongodb_key = "M.S";
	private String mongodb_value = "M.V";
	private String po_key = "S";
	private String po_value = "V";


	@SuppressWarnings({ "unused" })
	public void findHistoryDatasSnap(String point, Long beginDate, Long endDate, Long count, Long pried, List<PointData> ls, JedisPool jedisPool2) throws Exception {

		if (InitialRunner.rmcmap.containsKey(point)) {

			Date beginQuery = new Date(beginDate * 1000);
			Date endQuery = new Date(endDate * 1000);

			RMConfig rmc = InitialRunner.rmcmap.get(point);

			Calendar cal = Calendar.getInstance();
			cal.set(Calendar.HOUR_OF_DAY, 0);
			cal.set(Calendar.MINUTE, 0);
			cal.set(Calendar.SECOND, 0);
			cal.set(Calendar.MILLISECOND, 0);

			Date begin = cal.getTime();
			cal.add(Calendar.DAY_OF_MONTH, 1);
			Date end = cal.getTime();
			// 当前日期
			if (beginQuery.getTime() >= (begin.getTime()) && endQuery.getTime() <= (end.getTime())) {

				relData(point, count, pried, ls, jedisPool2, beginQuery, rmc, cal);

			} else if (beginQuery.getTime() < (begin.getTime()) && endQuery.getTime() <= (begin.getTime())) {

				hisData(point, count, pried, ls, jedisPool2, beginQuery, endQuery, rmc, cal);
			} else if (beginQuery.getTime() == (begin.getTime()) && endQuery.getTime() > (end.getTime())) {

				relData(point, count, pried, ls, jedisPool2, beginQuery, rmc, cal);

			} else if (beginQuery.getTime() < (begin.getTime())) {

				// realAndhistData(point, count, pried, ls, jedisPool2,
				// beginQuery, endQuery, rmc, cal);
				hisData(point, count, pried, ls, jedisPool2, beginQuery, endQuery, rmc, cal);
			}

			// mongoClient.close();
		}

	}

	@SuppressWarnings("unchecked")
	private void realAndhistData(String point, Long count, Long pried, List<PointData> ls, JedisPool jedisPool2, Date beginQuery, Date endQuery, RMConfig rmc, Calendar cal) throws Exception {
		// Map<Integer, Double> tempmap = new HashMap<Integer, Double>();
		Map<Integer, Double> tempmap = new TreeMap<Integer, Double>(new Comparator<Integer>() {
			public int compare(Integer obj1, Integer obj2) {
				// 升序排序
				return obj1.compareTo(obj2);
			}
		});
		StringBuilder sdb = new StringBuilder();

		int db = rmc.getMongodbindex();

		sdb.append(mongodb_db).append(db);

		// MongoClient mongoClient = new MongoClient(mongodb_ip,
		// mongodb_port);// 创建客户端
		MongoClient mongoClient = ApiMongoDb.getInstance();// 创建客户端
		MongoDatabase mongoDatabase = mongoClient.getDatabase(String.valueOf(sdb));// 获得数据库名
		StringBuilder sc = new StringBuilder();
		sc.append(mongodb_c).append(rmc.getCollindex());
		MongoCollection<Document> collection = mongoDatabase.getCollection(String.valueOf(sc));// 获得集合名字

		BasicDBObject fields = new BasicDBObject();
		fields.put("_id", 0);
		fields.put(mongodb_key, 1);
		fields.put(mongodb_value, 1);
		BasicDBObject query = new BasicDBObject();
		List<DBObject> phoneList = Lists.newArrayList();
		phoneList.add(new BasicDBObject(mongodb_p, rmc.getUkey()));

		Long time = beginQuery.getTime() / 1000;
		phoneList.add(new BasicDBObject(mongodb_key, new BasicDBObject("$gte", time)));
		time = endQuery.getTime() / 1000;
		phoneList.add(new BasicDBObject(mongodb_key, new BasicDBObject("$lte", time)));
		query.put("$and", phoneList);
		FindIterable<Document> docs = collection.find(query).projection(fields);

		MongoCursor<Document> mongoCursor = docs.iterator();
		// int i = 0;
		while (mongoCursor.hasNext()) {

			List<Document> vos = (List<Document>) mongoCursor.next().get(mongodb_ls);
			for (Document dc : vos) {
				tempmap.put(dc.getInteger(po_key), dc.getDouble(po_value));
			}

		}

		if (StringUtils.isNotNull(rmc.getUkey()) && StringUtils.isNotNull(rmc.getMongodbindex())) {
			Jedis jedis = jedisPool2.getResource();
			jedis.select(rmc.getMongodbindex());
			Map<String, String> hmap = jedis.hgetAll(String.valueOf(rmc.getUkey()));

			if (StringUtils.isNotNull(hmap)) {
				String str = hmap.get("1");
				JSONArray array = JSONArray.parseArray(str);
				if (StringUtils.isNotNull(array)) {
					for (int i = 0; i < array.size(); i++) {
						Map<String, Object> m = (Map<String, Object>) array.get(i);
						double value = Double.valueOf(String.valueOf(m.get(po_value)));
						// //System.out.println("S:"++"_V:"+m.get(po_value));
						tempmap.put(Integer.valueOf(String.valueOf(m.get(po_key))), value);
					}

				}

			}
			jedis.close();
		}

		/*******************************************************************************************************/
		if (StringUtils.isNotNull(rmc.getUkey()) && StringUtils.isNotNull(rmc.getMongodbindex())) {
			Jedis jedis = jedisPool2.getResource();
			jedis.select(rmc.getMongodbindex());
			Map<String, String> hmap = jedis.hgetAll(String.valueOf(rmc.getUkey()));

			if (StringUtils.isNotNull(hmap)) {
				String str = hmap.get("3");
				JSONArray array = JSONArray.parseArray(str);

				Calendar c = Calendar.getInstance();
				c.set(Calendar.HOUR_OF_DAY, 0);
				c.set(Calendar.MINUTE, 0);
				c.set(Calendar.SECOND, 0);
				Long begin = c.getTime().getTime() / 1000;
				if (StringUtils.isNotNull(array)) {
					for (int i = 0; i < array.size(); i++) {
						Map<String, Object> m = (Map<String, Object>) array.get(i);

						int key = Integer.valueOf(String.valueOf(m.get(po_key)));

						if (key == begin) {
							double value = Double.valueOf(String.valueOf(m.get(po_value)));
							// //System.out.println("S:"++"_V:"+m.get(po_value));
							tempmap.put(Integer.valueOf(String.valueOf(m.get(po_key))), value);

							break;
						}

					}

				}

			}

			jedis.close();
		}


		cal.setTime(beginQuery);

		for (int i = 0; i < count + 1; i++) {
			Long querydate = cal.getTime().getTime() / 1000;
			PointData po = new PointData();
			po.setEdnaId(point);
			po.setPointTime(querydate);

			if (tempmap.containsKey(querydate.intValue())) {

				po.setPointValueInDouble(tempmap.get(querydate.intValue()));
			} else {
				int num = 0;
				double tempvalue = 0.0;
				Set<Map.Entry<Integer, Double>> set = tempmap.entrySet();
				for (Iterator<Map.Entry<Integer, Double>> it = set.iterator(); it.hasNext();) {
					Map.Entry<Integer, Double> entry = (Map.Entry<Integer, Double>) it.next();

					if (entry.getKey() > querydate.intValue()) {

						break;
					} else {
						po.setPointValueInDouble(entry.getValue());
					}

				}
			}
			ls.add(po);
			cal.add(Calendar.SECOND, pried.intValue());

		}
	}

	@SuppressWarnings("unchecked")
	private void hisData(String point, Long count, Long pried, List<PointData> ls, JedisPool jedisPool2, Date beginQuery, Date endQuery, RMConfig rmc, Calendar cal) throws Exception {

		StringBuilder sdb = new StringBuilder();

		int db = rmc.getMongodbindex();

		sdb.append(mongodb_db).append(db);

		// MongoClient mongoClient = new MongoClient(mongodb_ip,
		// mongodb_port);// 创建客户端
		MongoClient mongoClient = ApiMongoDb.getInstance();// 创建客户端
		MongoDatabase mongoDatabase = mongoClient.getDatabase(String.valueOf(sdb));// 获得数据库名
		StringBuilder sc = new StringBuilder();
		sc.append(mongodb_c).append(rmc.getCollindex());
		MongoCollection<Document> collection = mongoDatabase.getCollection(String.valueOf(sc));// 获得集合名字

		BasicDBObject fields = new BasicDBObject();
		fields.put("_id", 0);
		fields.put(mongodb_key, 1);
		fields.put(mongodb_value, 1);
		Map<Integer, Double> map = new TreeMap<Integer, Double>(new Comparator<Integer>() {
			public int compare(Integer obj1, Integer obj2) {
				// 升序排序
				return obj1.compareTo(obj2);
			}
		});


		BasicDBObject query = new BasicDBObject();
		List<DBObject> phoneList = Lists.newArrayList();
		phoneList.add(new BasicDBObject(mongodb_p, rmc.getUkey()));
		phoneList.add(new BasicDBObject(mongodb_key, new BasicDBObject("$lt", beginQuery.getTime() / 1000)));
		query.put("$and", phoneList);

		Document doc = collection.find(query).projection(fields).first();
		if (StringUtils.isNotNull(doc)) {
			List<Document> vos = (List<Document>) doc.get(mongodb_ls);
			if (StringUtils.isNotNull(vos) && !vos.isEmpty()) {
				Document dc = vos.get(vos.size() - 1);
				map.put(dc.getInteger(po_key), dc.getDouble(po_value));
			}
		}

		query = new BasicDBObject();
		phoneList = Lists.newArrayList();
		phoneList.add(new BasicDBObject(mongodb_p, rmc.getUkey()));

		Long time = beginQuery.getTime() / 1000;
		phoneList.add(new BasicDBObject(mongodb_key, new BasicDBObject("$gte", time)));
		time = endQuery.getTime() / 1000;
		phoneList.add(new BasicDBObject(mongodb_key, new BasicDBObject("$lte", time)));
		query.put("$and", phoneList);
		FindIterable<Document> docs = collection.find(query).projection(fields);
		// Map<Integer, Double> map = new HashMap<Integer, Double>();

		MongoCursor<Document> mongoCursor = docs.iterator();
		// int i = 0;
		while (mongoCursor.hasNext()) {

			List<Document> vos = (List<Document>) mongoCursor.next().get(mongodb_ls);
			for (Document dc : vos) {
				map.put(dc.getInteger(po_key), dc.getDouble(po_value));
			}
			// //System.out.println(i + "___" + mongoCursor.next());
			// i++;
		}
		/*******************************************************************************************************/
		if (StringUtils.isNotNull(rmc.getUkey()) && StringUtils.isNotNull(rmc.getMongodbindex())) {
			Jedis jedis = jedisPool2.getResource();
			jedis.select(rmc.getMongodbindex());
			Map<String, String> hmap = jedis.hgetAll(String.valueOf(rmc.getUkey()));

			if (StringUtils.isNotNull(hmap)) {

				String str = hmap.get("3");
				JSONArray array = JSONArray.parseArray(str);


				if (StringUtils.isNotNull(array)) {
					for (int i = 0; i < array.size(); i++) {
						Map<String, Object> m = (Map<String, Object>) array.get(i);

						int key = Integer.valueOf(String.valueOf(m.get(po_key)));

						double value = Double.valueOf(String.valueOf(m.get(po_value)));

						map.put(key, value);

					}

				}

				String str2 = hmap.get("1");
				JSONArray array2 = JSONArray.parseArray(str2);

				if (StringUtils.isNotNull(array2)) {
					for (int i = 0; i < array2.size(); i++) {
						Map<String, Object> m = (Map<String, Object>) array2.get(i);
						double value = Double.valueOf(String.valueOf(m.get(po_value)));
						// //System.out.println("S:"++"_V:"+m.get(po_value));
						map.put(Integer.valueOf(String.valueOf(m.get(po_key))), value);
					}
				}

			}

			jedis.close();
		}

		/*******************************************************************************************************/
		cal.setTime(beginQuery);

		for (int i = 0; i < count + 1; i++) {
			Long querydate = cal.getTime().getTime() / 1000;

			PointData po = new PointData();
			po.setEdnaId(point);
			po.setPointTime(querydate);

			if (map.containsKey(querydate.intValue())) {

				po.setPointValueInDouble(map.get(querydate.intValue()));
			} else {

				Set<Map.Entry<Integer, Double>> set = map.entrySet();
				for (Iterator<Map.Entry<Integer, Double>> it = set.iterator(); it.hasNext();) {
					Map.Entry<Integer, Double> entry = (Map.Entry<Integer, Double>) it.next();

					if (entry.getKey() > querydate.intValue()) {

						break;
					} else {
						po.setPointValueInDouble(entry.getValue());
					}

				}
			}
			ls.add(po);
			cal.add(Calendar.SECOND, pried.intValue());

		}
	}

	@SuppressWarnings("unchecked")
	private void relData(String point, Long count, Long pried, List<PointData> ls, JedisPool jedisPool2, Date beginQuery, RMConfig rmc, Calendar cal) {
		if (StringUtils.isNotNull(rmc.getUkey()) && StringUtils.isNotNull(rmc.getMongodbindex())) {
			Jedis jedis = jedisPool2.getResource();
			jedis.select(rmc.getMongodbindex());
			Map<String, String> map = jedis.hgetAll(String.valueOf(rmc.getUkey()));

			// Map<Integer, Double> tempmap = new HashMap<Integer, Double>();
			Map<Integer, Double> tempmap = new TreeMap<Integer, Double>(new Comparator<Integer>() {
				public int compare(Integer obj1, Integer obj2) {
					// 升序排序
					return obj1.compareTo(obj2);
				}
			});
			if (StringUtils.isNotNull(map)) {
				String str = map.get("1");
				JSONArray array = JSONArray.parseArray(str);

				String str2 = map.get("3");
				JSONArray array2 = JSONArray.parseArray(str2);
				if (StringUtils.isNotNull(array)) {
					for (int i = 0; i < array.size(); i++) {
						Map<String, Object> m = (Map<String, Object>) array.get(i);
						double value = Double.valueOf(String.valueOf(m.get(po_value)));
						// //System.out.println("S:"++"_V:"+m.get(po_value));
						tempmap.put(Integer.valueOf(String.valueOf(m.get(po_key))), value);
					}

					Calendar c = Calendar.getInstance();
					c.set(Calendar.HOUR_OF_DAY, 0);
					c.set(Calendar.MINUTE, 0);
					c.set(Calendar.SECOND, 0);
					Long begin = c.getTime().getTime() / 1000;
					if (StringUtils.isNotNull(array2)) {
						for (int i = 0; i < array2.size(); i++) {
							Map<String, Object> m = (Map<String, Object>) array2.get(i);

							int key = Integer.valueOf(String.valueOf(m.get(po_key)));

							if (key == begin) {
								double value = Double.valueOf(String.valueOf(m.get(po_value)));
								// //System.out.println("S:"++"_V:"+m.get(po_value));
								tempmap.put(Integer.valueOf(String.valueOf(m.get(po_key))), value);

								break;
							}

						}

					}
					cal.setTime(beginQuery);

					for (int i = 0; i < count + 1; i++) {
						Long querydate = cal.getTime().getTime() / 1000;
						PointData po = new PointData();
						po.setEdnaId(point);
						po.setPointTime(querydate);

						if (tempmap.containsKey(querydate.intValue())) {

							po.setPointValueInDouble(tempmap.get(querydate.intValue()));
						} else {
							int num = 0;
							double tempvalue = 0.0;
							Set<Map.Entry<Integer, Double>> set = tempmap.entrySet();
							for (Iterator<Map.Entry<Integer, Double>> it = set.iterator(); it.hasNext();) {
								Map.Entry<Integer, Double> entry = (Map.Entry<Integer, Double>) it.next();

								if (entry.getKey() > querydate.intValue()) {

									break;
								} else {
									po.setPointValueInDouble(entry.getValue());
								}
							}
						}
						ls.add(po);
						cal.add(Calendar.SECOND, pried.intValue());
					}
				}

			}

			/*******************************************************************************************************/

			jedis.close();
		}
	}

}
