package org.ourfilesystem.test.ui.db;

/*
OurFileSystem is a peer2peer file sharing program.
Copyright (C) 2012  Robert Gass

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

*/

import static org.junit.Assert.*;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Random;

import org.junit.Test;
import org.ourfilesystem.db.LocalPost;
import org.ourfilesystem.db.Post;
import org.ourfilesystem.postcodec.Codec;
import org.ourfilesystem.postcodec.PostDecoded;
import org.ourfilesystem.ui.db.DBImpl;
import org.ourfilesystem.ui.db.QueryResultsInterface;
import org.ourfilesystem.utilities.BBytes;

public class DBTest {
	
	@Test
	public void testDB() {
		File f = new File("test.db");
		f.delete();
		
		DBImpl d = new DBImpl("test.db");
		
		Random r = new Random();
		
		byte frb0[] = new byte[20];
		r.nextBytes(frb0);
		byte frb1[] = new byte[20];
		r.nextBytes(frb1);
		byte frb2[] = new byte[20];
		r.nextBytes(frb2);
		byte frb3[] = new byte[20];
		r.nextBytes(frb3);
		
		BBytes fr0 = new BBytes(frb0);
		BBytes fr1 = new BBytes(frb1);
		BBytes fr2 = new BBytes(frb2);
		BBytes fr3 = new BBytes(frb3);
		
		Post p0 = new Post();
		p0.setFileReferenceDigest(fr0);
		p0.setPostNumber(10L);
		p0.setMessage(new File("p0.dat"));
		LocalPost lp0 = new LocalPost();
		lp0.setPost(p0);
		lp0.setLocalDate(new Date(10000000L));
		PostDecoded pd0 = new PostDecoded();
		pd0.setComment("This is a really cool like post dude.  Cool stuff.");
		pd0.getNumberValues().put("RANK", 10L);
		pd0.pushStringValue("KEYWORD", "cool");
		pd0.pushStringValue("KEYWORD", "fancy");
		pd0.pushReferenceValue("DUPLICATE", fr3);
		pd0.setPost(lp0);

		Post p1 = new Post();
		p1.setFileReferenceDigest(fr1);
		p1.setPostNumber(11L);
		p1.setMessage(new File("p1.dat"));
		LocalPost lp1 = new LocalPost();
		lp1.setPost(p1);
		lp1.setLocalDate(new Date(11000000L));
		PostDecoded pd1 = new PostDecoded();
		pd1.setComment("This is NOT very cool man.  WHO WOULD DO THAT!");
		pd1.getNumberValues().put("RANK", 13L);
		pd1.getNumberValues().put("NUMBER", 99L);
		pd1.pushStringValue("KEYWORD", "NOT_COOL");
		pd1.pushStringValue("KEYWORD", "NOT_FANCY");
		pd1.setPost(lp1);

		Post p2 = new Post();
		p2.setFileReferenceDigest(fr2);
		p2.setPostNumber(12L);
		p2.setMessage(new File("p2.dat"));
		LocalPost lp2 = new LocalPost();
		lp2.setPost(p2);
		lp2.setLocalDate(new Date(12000000L));
		PostDecoded pd2 = new PostDecoded();
		pd2.setComment("Some comments here.  Someone would sya something!");
		pd2.getNumberValues().put("RANK", 15L);
		pd2.getNumberValues().put("NUMBER", 99L);
		pd2.pushStringValue("KEYWORD", "NOT_COOL");
		pd2.pushStringValue("KEYWORD", "BLING");
		pd2.pushReferenceValue("DUPLICATE", fr1);
		pd2.setPost(lp2);

		try {
			Codec.ecnode(pd0);
			Codec.ecnode(pd1);
			Codec.ecnode(pd2);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		d.saveNewPost(pd0);
		d.saveNewPost(pd1);
		d.saveNewPost(pd2);

		//---------------------------------------------------------------------------------------------
		// Date search.
		//                 10000000L
		Date fd = new Date(9000000L);
		Date td = new Date(10500000L);
		QueryResultsInterface q = d.search(null,  //orstring,        
				 null,                            //andstring,
				 null,							  //excludestrings
				 null,                            //ornum,           
				 null,                            //andnums,         
				 null,                            //lessthan,        
				 null,                            //greaterthan,  
				 null,                            //averageless,
				 null,                            //averagegreater,
				 null,                            //excludebackrefs, 
				 null,                            //hasreferences,   
				 null,                            //directrefs
				 null,                            //includepeers,    
				 null,                            //excludepeers,    
				 fd,                              //fromd,           
				 td);                             //tod              
		
		assertEquals(q.size(), 1);
		PostDecoded pd0t = q.get(0);
		assertEquals(pd0t.getComment(), pd0.getComment());
		
		//---------------------------------------------------------------------------------------------
		// OR keyword search
		HashMap<String,HashSet<String>> keywords = new HashMap<String,HashSet<String>>();
		keywords.put("KEYWORD", new HashSet<String>());
		keywords.get("KEYWORD").add("NOT_FANCY");
		keywords.get("KEYWORD").add("BLING");
		
		q = d.search(keywords,                    //orstring,        
				 null,                            //andstring,       
				 null,							  //excludestrings
				 null,                            //ornum,           
				 null,                            //andnums,         
				 null,                            //lessthan,        
				 null,                            //greaterthan,     
				 null,                            //averageless,
				 null,                            //averagegreater,
				 null,                            //excludebackrefs, 
				 null,                            //hasreferences,   
				 null,                            //directrefs
				 null,                            //includepeers,    
				 null,                            //excludepeers,    
				 null,                            //fromd,           
				 null);                           //tod              

		assertEquals(q.size(), 2);
		PostDecoded pdAt = q.get(0);
		PostDecoded pdBt = q.get(1);
		
		boolean fnd11 = false;
		boolean fnd12 = false;
		
		if (pdAt.getPost().getPost().getPostNumber() == 11L) {
			fnd11 = true;
		}
		if (pdBt.getPost().getPost().getPostNumber() == 12L) {
			fnd12 = true;
		}
		assertTrue(fnd11);
		assertTrue(fnd12);
		
		
		//---------------------------------------------------------------------------------------------
		// AND keyword search
		keywords = new HashMap<String,HashSet<String>>();
		keywords.put("KEYWORD", new HashSet<String>());
		keywords.get("KEYWORD").add("NOT_FANCY");
		keywords.get("KEYWORD").add("NOT_COOL");
		
		q = d.search(null,                        //orstring,        
				 keywords,                        //andstring,       
				 null,							  //excludestrings
				 null,                            //ornum,           
				 null,                            //andnums,         
				 null,                            //lessthan,        
				 null,                            //greaterthan,     
				 null,                            //excludebackrefs, 
				 null,                            //averageless,
				 null,                            //averagegreater,
				 null,                            //hasreferences,   
				 null,                            //directrefs
				 null,                            //includepeers,    
				 null,                            //excludepeers,    
				 null,                            //fromd,           
				 null);                           //tod              

		assertEquals(q.size(), 1);
		pdAt = q.get(0);
		
		assertEquals(pdAt.getPost().getPost().getPostNumber(), 11L);
		
		//---------------------------------------------------------------------------------------------
		// or num search.
		HashMap<String,HashSet<Long>> numsearch = new HashMap<String,HashSet<Long>>();
		numsearch.put("NUMBER", new HashSet<Long>());
		numsearch.get("NUMBER").add(99L);
		
		q = d.search(null,                        //orstring,        
				 null,                            //andstring,       
				 null,							  //excludestrings
				 numsearch,                       //ornum,           
				 null,                            //andnums,         
				 null,                            //lessthan,        
				 null,                            //greaterthan,     
				 null,                            //averageless,
				 null,                            //averagegreater,
				 null,                            //excludebackrefs, 
				 null,                            //hasreferences,   
				 null,                            //directrefs
				 null,                            //includepeers,    
				 null,                            //excludepeers,    
				 null,                            //fromd,           
				 null);                           //tod              

		assertEquals(q.size(), 2);
		pdAt = q.get(0);
		pdBt = q.get(1);
		
		fnd11 = false;
		fnd12 = false;
		
		if (pdAt.getPost().getPost().getPostNumber() == 11L) {
			fnd11 = true;
		}
		if (pdBt.getPost().getPost().getPostNumber() == 12L) {
			fnd12 = true;
		}
		assertTrue(fnd11);
		assertTrue(fnd12);
		
		//---------------------------------------------------------------------------------------------
		// and num search.
		HashMap<String,Long> numand = new HashMap<String,Long>();
		numand.put("RANK", 13L);
		numand.put("NUMBER", 99L);

		q = d.search(null,                        //orstring,        
				 null,                            //andstring,       
				 null,							  //excludestrings
				 null,                            //ornum,           
				 numand,                          //andnums,         
				 null,                            //lessthan,        
				 null,                            //greaterthan,     
				 null,                            //averageless,
				 null,                            //averagegreater,
				 null,                            //excludebackrefs, 
				 null,                            //hasreferences,   
				 null,                            //directrefs
				 null,                            //includepeers,    
				 null,                            //excludepeers,    
				 null,                            //fromd,           
				 null);                           //tod              

		assertEquals(q.size(), 1);

		pdAt = q.get(0);
		
		assertEquals(pdAt.getPost().getPost().getPostNumber(), 11L);
		
		//---------------------------------------------------------------------------------------------
		// less than
		HashMap<String,Long> less = new HashMap<String,Long>();
		less.put("RANK", 11L);

		q = d.search(null,                        //orstring,        
				 null,                            //andstring,       
				 null,							  //excludestrings
				 null,                            //ornum,           
				 null,                            //andnums,         
				 less,                            //lessthan,        
				 null,                            //greaterthan,     
				 null,                            //averageless,
				 null,                            //averagegreater,
				 null,                            //excludebackrefs, 
				 null,                            //hasreferences,   
				 null,                            //directrefs
				 null,                            //includepeers,    
				 null,                            //excludepeers,    
				 null,                            //fromd,           
				 null);                           //tod              

		assertEquals(q.size(), 1);

		pdAt = q.get(0);
		
		assertEquals(pdAt.getPost().getPost().getPostNumber(), 10L);
		
		//---------------------------------------------------------------------------------------------
		// greater than
		HashMap<String,Long> gt = new HashMap<String,Long>();
		gt.put("RANK", 11L);

		q = d.search(null,                        //orstring,        
				 null,                            //andstring,       
				 null,							  //excludestrings
				 null,                            //ornum,           
				 null,                            //andnums,         
				 null,                            //lessthan,        
				 gt,                              //greaterthan,     
				 null,                            //averageless,
				 null,                            //averagegreater,
				 null,                            //excludebackrefs, 
				 null,                            //hasreferences,   
				 null,                            //directrefs
				 null,                            //includepeers,    
				 null,                            //excludepeers,    
				 null,                            //fromd,           
				 null);                           //tod              

		assertEquals(q.size(), 2);

		pdAt = q.get(0);
		pdBt = q.get(1);
		
		fnd11 = false;
		fnd12 = false;
		
		if (pdAt.getPost().getPost().getPostNumber() == 11L) {
			fnd11 = true;
		}
		if (pdBt.getPost().getPost().getPostNumber() == 12L) {
			fnd12 = true;
		}
		assertTrue(fnd11);
		assertTrue(fnd12);
		
		//---------------------------------------------------------------------------------------------
		// keyword seach, remove duplicates.
		keywords = new HashMap<String,HashSet<String>>();
		keywords.put("KEYWORD", new HashSet<String>());
		keywords.get("KEYWORD").add("NOT_COOL");
		
		HashSet<String> exback = new HashSet<String>();
		exback.add("DUPLICATE");
		
		q = d.search(null,                        //orstring,        
				 keywords,                        //andstring,       
				 null,							  //excludestrings
				 null,                            //ornum,           
				 null,                            //andnums,         
				 null,                            //lessthan,        
				 null,                            //greaterthan,     
				 null,                            //averageless,
				 null,                            //averagegreater,
				 exback,                          //excludebackrefs, 
				 null,                            //hasreferences,   
				 null,                            //directrefs
				 null,                            //includepeers,    
				 null,                            //excludepeers,    
				 null,                            //fromd,           
				 null);                           //tod              

		assertEquals(q.size(), 1);
		pdAt = q.get(0);
		
		assertEquals(pdAt.getPost().getPost().getPostNumber(), 11L);
		
		//---------------------------------------------------------------------------------------------
		// find duplicates.
		HashMap<String,HashSet<Object>> dups = new HashMap<String, HashSet<Object>>();
		HashSet<Object> hso = new HashSet<Object>();
		hso.add(fr1);
		dups.put("DUPLICATE", hso);
		
		q = d.search(null,                        //orstring,        
				 null,                            //andstring,       
				 null,							  //excludestrings
				 null,                            //ornum,           
				 null,                            //andnums,         
				 null,                            //lessthan,        
				 null,                            //greaterthan,     
				 null,                            //averageless,
				 null,                            //averagegreater,
				 null,                            //excludebackrefs, 
				 dups,                            //hasreferences,   
				 null,                            //directrefs
				 null,                            //includepeers,    
				 null,                            //excludepeers,    
				 null,                            //fromd,           
				 null);                           //tod              

		assertEquals(q.size(), 1);
		pdAt = q.get(0);
		
		assertEquals(pdAt.getPost().getPost().getPostNumber(), 12L);
		

}

}
