package com.vogella.jersey.first.util;

import static com.mongodb.client.model.Filters.and;
import static com.mongodb.client.model.Filters.eq;
import static com.mongodb.client.model.Filters.gte;
import static com.mongodb.client.model.Filters.lte;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.bson.Document;
import org.bson.conversions.Bson;

import com.google.gson.Gson;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.result.DeleteResult;
import com.vogella.jersey.first.model.ChatMessage;
import com.vogella.jersey.first.model.mapobject.Coin;
import com.vogella.jersey.first.model.mapobject.MapObject;

public class ChatManager{

	private final MongoCollection<Document> collection;
	private final MongoClient mongoClient;
	protected final Random random;

	public static final String COLLECTION_NAME = "chat";

	public ChatManager(MongoClient mongoClient,MongoCollection<Document> collection){
		this.mongoClient = mongoClient;
		this.collection = collection;
		this.random = new Random();
	}

	private static MongoCollection<Document> retrieveCollection(MongoClient mongoClient){
		try{
			return mongoClient.getDatabase(GameMongoDBUtils.DATABASE_NAME).getCollection(COLLECTION_NAME);
		}catch(Exception e){
			e.printStackTrace();
		}
		
		return null;
	}

	public ChatMessage insert(ChatMessage chatMessage){
		if(chatMessage != null){
			synchronized(this){
				chatMessage.id = getNewId();
				ChatMessage chatMessageDB = get(chatMessage.id);
				if(chatMessageDB == null){
					try{
						synchronized(this){
							collection.insertOne(chatMessage.getDocument());
						}
						return chatMessage;
					}catch(Exception e){
						e.printStackTrace();
					}
				}
			}
		}
		return null;
	}
	
	public List<ChatMessage> getByType(int type){
		deleteOldMessages();
		List<ChatMessage> chatMessages = new ArrayList<>();
		Gson gson = new Gson();
		FindIterable<Document> listDoc = null;
		try{
			synchronized(this){
				listDoc = collection.find(eq("type",type));
			}
			if(listDoc != null){
				MongoCursor<Document> cursor = listDoc.iterator();
				try{
					ChatMessage chatMessage;
					while(cursor.hasNext()){
						chatMessage = gson.fromJson(cursor.next().toJson(),ChatMessage.class);
						if(chatMessage != null){
							chatMessages.add(chatMessage);
						}
					}
					return chatMessages;
				}finally{
					try{
						cursor.close();
					}catch(Exception e){
						e.printStackTrace();
					}
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		return null;
	}

	private void deleteOldMessages(){
		try{
			synchronized(this){
				collection.deleteMany(lte("time",System.currentTimeMillis()-(1000*60*60)));	// 1 hour expire the messages
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		return;
	}

	public String getNewId(){
		String id = System.currentTimeMillis() + "," + System.nanoTime();
		ChatMessage chatMessage = get(id);
		while(chatMessage != null){
			id = System.currentTimeMillis() + "," + System.nanoTime();
			chatMessage = get(id);
		}
		return id;
	}
	
	public ChatMessage get(String id){
		try{
			Document doc;
			synchronized(this){
				doc = collection.find(eq(MapObject.KEY_ID,id)).first();
			}
			if(doc != null){
				Gson gson = new Gson();
				return gson.fromJson(doc.toJson(),ChatMessage.class);
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		return null;
	}
}