package com.gyee.frame.util.mongodb;


import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.Lists;
import com.gyee.frame.common.conf.MongodbConfig;
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.DateUtils;
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.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 */
public class HistoryStatUtil {



	private String mongodb_ip = MongodbConfig.mongodb_ip;
	private int mongodb_port = Integer.valueOf(MongodbConfig.mongodb_port);
	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";
	// private Logger logger = Logger.getLogger(this.getClass().getName());

	

	@SuppressWarnings({ "unused" })
	public void findHistoryDatasStat(String point, Long beginDate, Long endDate, Long pried, List<PointData> ls, JedisPool jedisPool2, int type) 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, pried, ls, jedisPool2, beginQuery, endQuery, rmc, cal, type);

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

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

				relData(point, pried, ls, jedisPool2, beginQuery, endQuery, rmc, cal, type);
				
//			} else if (beginQuery.getTime() < (begin.getTime()) && endQuery.getTime() >= (end.getTime())) {
			} else if (beginQuery.getTime() < (begin.getTime()) ) {
				
				realAndhistData(point, pried, ls, jedisPool2, beginQuery, endQuery, rmc, cal, type);
			}

			// mongoClient.close();
		}

	}

	@SuppressWarnings("unchecked")
	private void realAndhistData(String point,  Long pried, List<PointData> ls, JedisPool jedisPool2, Date beginQuery, Date endQuery, RMConfig rmc, Calendar cal, int type) throws Exception {
		Map<Integer, Double> tempmap = new HashMap<Integer, Double>();

		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));
			}
			// 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.isNotEmpty(hmap)) {
				String str = hmap.get("1");
				JSONArray array = JSONArray.parseArray(str);
				if (StringUtils.isNotEmpty(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.isNotEmpty(hmap)) {
				String str = hmap.get("3");
				JSONArray array = JSONArray.parseArray(str);
				
				Long begin = beginQuery.getTime() / 1000;
					Long end = endQuery.getTime() / 1000;
				if (StringUtils.isNotEmpty(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 && key<=end)
						{
							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();
		}
		
		/*******************************************************************************************************/
		setStatData(point, pried, ls, beginQuery, endQuery, cal, type, tempmap);
	}

	@SuppressWarnings("unchecked")
	private void hisData(String point,  Long pried, List<PointData> ls, JedisPool jedisPool2, Date beginQuery, Date endQuery, RMConfig rmc, Calendar cal, int type) 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);
		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);
		Map<Integer, Double> tempmap = 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) {
				tempmap.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.isNotEmpty(hmap)) {
				String str = hmap.get("3");
				JSONArray array = JSONArray.parseArray(str);
				
				Long begin = beginQuery.getTime() / 1000;
					Long end = endQuery.getTime() / 1000;
				if (StringUtils.isNotEmpty(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 && key<=end)
						{
							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();
		}
		
		/*******************************************************************************************************/
		setStatData(point, pried, ls, beginQuery, endQuery, cal, type, tempmap);

	}

	@SuppressWarnings("unchecked")
	private void relData(String point, Long pried, List<PointData> ls, JedisPool jedisPool2, Date beginQuery, Date endQuery, RMConfig rmc, Calendar cal, int type) {
		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>();
			if (StringUtils.isNotEmpty(map)) {
				String str = map.get("1");
				JSONArray array = JSONArray.parseArray(str);
				if (StringUtils.isNotEmpty(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);
					}
					setStatData(point, pried, ls, beginQuery, endQuery, cal, type, tempmap);
				}

			}
			jedis.close();
		}
	}

	private void setStatData(String point, Long pried, List<PointData> ls, Date beginQuery, Date endQuery, Calendar cal, int type, Map<Integer, Double> tempmap) {
		cal.setTime(beginQuery);

		int num = DateUtils.minutesDiff(beginQuery, endQuery);

		int step = 0;
		double total = 0;
		double max = 0.0;
		double min = 0.0;
		num = num + 1;

		for (int i = 0; i < num; i++) {

			Long temp = cal.getTime().getTime() / 1000;

			

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

				double dtemp = tempmap.get(temp.intValue());

				if (step == pried) {

					PointData po = new PointData();
					po.setEdnaId(point);
					po.setPointTime(temp);
					
					switch (type) {
					case 0:
						po.setPointValueInDouble(max);
						break;
					case 1:
						po.setPointValueInDouble(min);
						break;
					case 2:
						total = new BigDecimal(total).divide(new BigDecimal(step), 2, RoundingMode.HALF_EVEN).doubleValue();
						po.setPointValueInDouble(total);
						break;
					default:
						break;
					}
					
					ls.add(po);
					total = 0;
					step = 0;
					max = dtemp;
					min = dtemp;
				}

				if (i == 0) {
					max = dtemp;
					min = dtemp;
				}

				if (dtemp > max) {
					max = dtemp;
				} else if (dtemp < min) {
					min = dtemp;
				}

				total = total + dtemp;
				step++;

			}

			cal.add(Calendar.MINUTE, 1);

		}
	}
}
