package com.zhiwei.manage.dao;

import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.Resource;

import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Component;

import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.WriteResult;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.connection.Server;
import com.zhiwei.manage.bean.Data;
import com.zhiwei.manage.bean.EasyNews;
import com.zhiwei.manage.bean.News;
import com.zhiwei.manage.bean.ServerBean;
import com.zhiwei.manage.bean.Template;
import com.zhiwei.manage.bean.Weibo;
import com.zhiwei.manage.handle.DbDepot;
import com.zhiwei.manage.util.Change;
import com.zhiwei.manage.util.MongoConnect;

@SuppressWarnings({ "all" })
@Component
public class DataDaoImpl implements DataDao {

	@Resource(name = "mongoTemplate")
	private MongoTemplate mongo;
	@Resource(name = "newmongoTemplate")
	private MongoTemplate mongo2;

	@Override
	public List<Data> findByPt(Date startTime, Date endTime, String pt) {
		Criteria criteria = new Criteria();
		criteria.and("pt").is(pt);
		criteria.and("time").gt(startTime).lt(endTime);
		criteria.and("tempName").exists(false);
		return mongo.find(Query.query(criteria), Data.class, "Data");
	}

	@Override
	public List<Data> findBySource(Date startTime, Date endTime, String source) {
		Criteria criteria = new Criteria();
		criteria.and("source").regex(source);
		criteria.and("time").gte(startTime).lt(endTime);
		return mongo.find(Query.query(criteria), Data.class, "Data");
	}

	@Override
	public List<Data> findBytempName(Date startTime, Date endTime, String tempName) {
		Criteria criteria = new Criteria();
		criteria.and("tempName").regex(tempName);
		criteria.and("time").gte(startTime).lt(endTime);
		return mongo.find(Query.query(criteria), Data.class, "Data");
	}

	@Override
	public void insert(Data data) {
		Data d = null;
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
		Date today=null;
		try {
			today=sdf.parse(sdf.format(data.getTime()));
		} catch (ParseException e1) {
			e1.printStackTrace();
		}
		if (data.getTempName() != null) {
			d = mongo.findOne(Query.query(Criteria.where("time").is(today)
					.andOperator(Criteria.where("tempName").is(data.getTempName()))), Data.class);
		} else {
			d = mongo.findOne(Query.query(
					Criteria.where("time").is(today).andOperator(Criteria.where("pt").is(data.getPt()))),
					Data.class);
		}
		if (d == null) {
			mongo.insert(data, "Data");
		}else {
			d.setCount(data.getCount() + d.getCount());
			Update update = new Update();
			Field[] fields = d.getClass().getDeclaredFields();
			for (int j = 0; j < fields.length; j++) {
				fields[j].setAccessible(true);
				try {
					if (fields[j].getName().equals("dataId")) {
						continue;
					}else if(fields[j].getName().equals("time")) {
						update.set(fields[j].getName(), today);
					}
					if (fields[j].get(d) != null)
						update.set(fields[j].getName(), fields[j].get(d));
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			mongo.updateFirst(Query.query(Criteria.where("_id").is(d.getDataId())), update,
					Data.class);
		}
	}

	@Override
	public List<EasyNews> findByAccurateSource(String startTime, String endTime, String source) {
		Calendar c = Calendar.getInstance();
		int month = c.get(Calendar.MONTH) + 1;
		int year = c.get(Calendar.YEAR);
		Criteria criteria = new Criteria();
		criteria.and("source").regex(source);
		criteria.and("time").gte(startTime).lt(endTime);
		return mongo2.find(Query.query(criteria), EasyNews.class,
				"net_media_" + year + (month > 9 ? "" + month : "0" + month));
	}

	@Override
	public List<EasyNews> findByAccurateSpId(String startTime, String endTime, String SpId) {
		Calendar c = Calendar.getInstance();
		int month = c.get(Calendar.MONTH) + 1;
		int year = c.get(Calendar.YEAR);
		Criteria criteria = new Criteria();
		criteria.and("spyderInfoId").is(SpId);
		criteria.and("time").gt(startTime).lt(endTime);
		return mongo2.find(Query.query(criteria), EasyNews.class,
				"net_media_" + year + (month > 9 ? "" + month : "0" + month));
	}

	@Override
	public long finCountByDayData(Date startTime, Date endTime, String pt) {
		String end = "";
		Calendar cal = Calendar.getInstance();
		cal.setTime(startTime);
		MongoCollection<Document> col = null;
		if (pt.equals("知乎")) {
			if (DbDepot.dataCol != null) {
				if (DbDepot.dataCol.get(pt) != null && DbDepot.month == cal.get(Calendar.MONTH)) {
					col = (MongoCollection<Document>) DbDepot.dataCol.get(pt);
				}
			}
			int resultCount = 0;
			if (col == null) {
				ServerBean ser = mongo.findOne(
						Query.query(Criteria.where("pt").is(pt).andOperator(Criteria.where("other").is("data"))),
						ServerBean.class);
				MongoClient mongoClient = new MongoClient(ser.getDbHost(), ser.getDbPort());
				// 连接到数据库
				MongoDatabase mongo = mongoClient.getDatabase(ser.getDbName());
				for (int i = 1; i < 6; i++) {
					col = mongo.getCollection(ser.getCollection() + i);
					Bson query = new BasicDBObject("update_at",
							new BasicDBObject("$gte", startTime).append("$lte", endTime));
					resultCount += col.count(query);
				}
			}
			return resultCount;
		}
		col = getcol(startTime, endTime, pt);
		long count = 0;
		if (pt.equals("微博")) {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
			Bson query = new BasicDBObject("time",
					new BasicDBObject("$gte", sdf.format(startTime)).append("$lte", sdf.format(endTime)));
			count = col.count(query);
		} else if (pt.equals("微信") || pt.equals("网媒") || pt.equals("论坛") || pt.equals("贴吧") || pt.equals("平媒")) {
			Bson query = new BasicDBObject("time", new BasicDBObject("$gte", startTime).append("$lte", endTime))
					.append("pt", pt);
			count = col.count(query);
		} else {
			Bson query = new BasicDBObject("time", new BasicDBObject("$gte", startTime).append("$lte", endTime));
			count = col.count(query);
		}
		return count;
	}

	@Override
	public long finCountByDayData(Date startTime, Date endTime, Template temp) {
		String end = "";
		Calendar cal = Calendar.getInstance();
		String pt = temp.getPt();
		cal.setTime(startTime);
		MongoCollection<Document> col = getcol(startTime, endTime, pt);
		Bson query = new BasicDBObject("time", new BasicDBObject("$gte", startTime).append("$lte", endTime))
				.append("spyderInfoId", temp.getSpyderInfoId());
		return col.count(query);
	}

	public MongoCollection<Document> getcol(Date startTime, Date endTime, String pt) {
		String end = "";
		Calendar cal = Calendar.getInstance();
		cal.setTime(startTime);
		if (DbDepot.dataCol != null) {
			if (DbDepot.dataCol.get(pt) != null && DbDepot.month == cal.get(Calendar.MONTH)) {
				return (MongoCollection<Document>) DbDepot.dataCol.get(pt);
			} else {
				ServerBean ser = mongo.findOne(
						Query.query(Criteria.where("pt").is(pt).andOperator(Criteria.where("other").is("data"))),
						ServerBean.class);
				if (ser.isTable()) {
					int month = cal.get(Calendar.MONTH) + 1;
					end = cal.get(Calendar.YEAR) + "" + (month > 9 ? "" + month : "0" + month);
					System.out.println(end);
				}
				MongoClient mongoClient = null;
				if (ser.getDbUsername() != null && ser.getDbUsername().length() > 2) {
					ServerAddress sa = new ServerAddress(ser.getDbHost(), ser.getDbPort());
					List<MongoCredential> mongoCredentialList = new ArrayList<MongoCredential>();
					mongoCredentialList.add(MongoCredential.createMongoCRCredential(ser.getDbUsername(),
							ser.getDbName(), ser.getDbPassword().toCharArray()));
					new MongoClient(sa, mongoCredentialList);
					mongoClient = new MongoClient(sa, mongoCredentialList);
				} else
					mongoClient = new MongoClient(ser.getDbHost(), ser.getDbPort());
				// 连接到数据库
				MongoDatabase mongo = mongoClient.getDatabase(ser.getDbName());
				DbDepot.dataCol.put(pt, mongo.getCollection(ser.getCollection() + end));
				DbDepot.month = cal.get(Calendar.MONTH);
				return mongo.getCollection(ser.getCollection() + end);
			}
		} else {
			DbDepot.dataCol = new ConcurrentHashMap<String, Object>();
			ServerBean ser = mongo.findOne(
					Query.query(Criteria.where("pt").is(pt).andOperator(Criteria.where("other").is("data"))),
					ServerBean.class);
			if (ser.isTable()) {
				int month = cal.get(Calendar.MONTH) + 1;
				end = cal.get(Calendar.YEAR) + "" + (month > 9 ? "" + month : "0" + month);
			}
			MongoClient mongoClient = null;
			if (ser.getDbUsername() != null) {
				ServerAddress sa = new ServerAddress(ser.getDbHost(), ser.getDbPort());
				List<MongoCredential> mongoCredentialList = new ArrayList<MongoCredential>();
				mongoCredentialList.add(MongoCredential.createMongoCRCredential(ser.getDbUsername(), ser.getDbName(),
						ser.getDbPassword().toCharArray()));
				mongoClient = new MongoClient(sa, mongoCredentialList);
			} else
				mongoClient = new MongoClient(ser.getDbHost(), ser.getDbPort());
			MongoDatabase mongo = mongoClient.getDatabase(ser.getDbName());
			DbDepot.dataCol.put(pt, mongo.getCollection(ser.getCollection() + end));
			return mongo.getCollection(ser.getCollection() + end);
		}
	}

	public static void main(String[] args) {
		// 连接到数据库
		ServerAddress sa = new ServerAddress("115.236.59.91", 27017);
		List<MongoCredential> mongoCredentialList = new ArrayList<MongoCredential>();
		MongoClient mongoClient = new MongoClient(sa, mongoCredentialList);
		MongoDatabase mongo = mongoClient.getDatabase("mediaspider");
		MongoCollection<Document> col = mongo.getCollection("net_media_201801");
		System.out.println(col.count());
	}

	@Override
	public int findBySourceFromLibrary(Date startTime, Date endTime, String source) {
		Calendar c = Calendar.getInstance();
		c.setTime(startTime);
		int year = c.get(Calendar.YEAR);
		int month = c.get(Calendar.MONTH) + 1;
		return (int) mongo2.count(Query.query(Criteria.where("time").gte(startTime).lt(endTime).and("type").is(source)),
				EasyNews.class, "net_media_" + year + (month > 9 ? "" + month : "0" + month));
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<String> findSourceByLikeParam(String param) {
		Calendar c = Calendar.getInstance();
		int year = c.get(Calendar.YEAR);
		int month = c.get(Calendar.MONTH) + 1;
		try {
			return mongo2.getCollection("net_media_" + year + (month > 9 ? "" + month : "0" + month)).distinct("source",
					new BasicDBObject("source", new BasicDBObject("$regex", param)));
		} catch (Exception e) {
			return mongo2.getCollection("net_media_" + year + (month > 9 ? "" + month : "0" + month)).distinct("source",
					new BasicDBObject("source", new BasicDBObject("$regex", param)));
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<String> findTmpNameByLikeParam(String param) {
		try {
			return mongo.getCollection("Data").distinct("tempName",
					new BasicDBObject("tempName", new BasicDBObject("$regex", param)));
		} catch (Exception e) {
			return mongo.getCollection("Data").distinct("tempName",
					new BasicDBObject("tempName", new BasicDBObject("$regex", param)));
		}
	}

	@Override
	public int findByAccurateType(Date startTime, Date endTime, String type) {
		Calendar c = Calendar.getInstance();
		c.setTime(startTime);
		int year = c.get(Calendar.YEAR);
		int month = c.get(Calendar.MONTH) + 1;
		return (int) mongo2.count(Query.query(Criteria.where("time").gte(startTime).lt(endTime).and("type").is(type)),
				EasyNews.class, "net_media_" + year + (month > 9 ? "" + month : "0" + month));
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<String> findTypeByLikeParam(String param) {
		Calendar c = Calendar.getInstance();
		int year = c.get(Calendar.YEAR);
		int month = c.get(Calendar.MONTH) + 1;
		try {
			DBObject obj = new BasicDBObject();
			obj.put("pt", new BasicDBObject("$ne", "微信"));
			obj.put("type", new BasicDBObject("$regex", param));
			return mongo2.getCollection("net_media_" + year + (month > 9 ? "" + month : "0" + month)).distinct("type",
					obj);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public List<Data> findByMethod(Date startTime, Date endTime, String method, Object value) {
		List<Data> list = new ArrayList<Data>();
		if (DbDepot.dbCons.get("data") != null) {
			DBCollection coll = (DBCollection) DbDepot.dbCons.get("data");
			DBObject obj = new BasicDBObject();
			if (method != null) {
				obj.put(method, value);
				obj.put("time", new BasicDBObject("$gte", startTime).append("$lt", endTime));
			} else {
				obj.put("time", new BasicDBObject("$gte", startTime).append("$lt", endTime));
			}
			DBCursor cursor = coll.find(obj).sort(new BasicDBObject("time", -1));
			while (cursor.hasNext()) {
				Map<String, Object> map = (Map<String, Object>) cursor.next();
				Data d = Change.toBean(Data.class, map);
				list.add(d);
			}
			cursor.close();
		} else {
			System.out.println("user------------------");
			ServerBean sb = mongo.findOne(Query.query(Criteria.where("other").is("data")), ServerBean.class);
			DBCollection coll = null;
			if (sb.getDbUsername() == null || sb.getDbUsername().equals("")) {
				coll = new MongoConnect(sb.getDbHost(), sb.getDbPort(), sb.getDbName())
						.getCollection(sb.getCollection());
			} else {
				coll = new MongoConnect(sb.getDbHost(), sb.getDbPort(), sb.getDbUsername(), sb.getDbPassword(),
						sb.getDbName()).getCollection(sb.getCollection());
				DbDepot.dbCons.put(sb.getOther(), coll);
			}
			DBObject obj = new BasicDBObject();
			if (method != null) {
				obj.put(method, value);
				obj.put("time", new BasicDBObject("$gte", startTime).append("$lt", endTime));
			} else {
				obj.put("time", new BasicDBObject("$gte", startTime).append("$lt", endTime));
			}
			DBCursor cursor = coll.find(obj).sort(new BasicDBObject("time", -1));
			while (cursor.hasNext()) {
				Map<String, Object> map = (Map<String, Object>) cursor.next();
				Data d = Change.toBean(Data.class, map);
				list.add(d);
			}
			cursor.close();
		}
		return list;
	}

	@Override
	public int findBySpId(Date startTime, Date endTime, String syId) {
		Calendar c = Calendar.getInstance();
		c.setTime(startTime);
		int year = c.get(Calendar.YEAR);
		int month = c.get(Calendar.MONTH) + 1;
		return (int) mongo2.count(
				Query.query(Criteria.where("time").gte(startTime).lt(endTime).and("spyderInfoId").is(syId)),
				EasyNews.class, "net_media_" + year + (month > 9 ? "" + month : "0" + month));
	}

}
