package org.ourfilesystem.test.core;

/*
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.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.util.Date;
import java.util.List;

import org.junit.Test;
import org.ourfilesystem.com.ComConnectionImpl;
import org.ourfilesystem.com.SimpleConnector;
import org.ourfilesystem.com.SimpleServerSocket;
import org.ourfilesystem.core.Core;
import org.ourfilesystem.db.DataBaseComImpl;
import org.ourfilesystem.db.LocalPost;
import org.ourfilesystem.db.Peer;
import org.ourfilesystem.db.StorageImpl;
import org.ourfilesystem.db.TimeImpl;
import org.ourfilesystem.security.CryptoComImpl;
import org.ourfilesystem.security.CryptoDataBaseImpl;
import org.ourfilesystem.utilities.FileUtils;

public class CoreTest {
	
	public Core buildCore(String basedir, int port) throws IOException {
		Core c = new Core();
		StorageImpl store = new StorageImpl(basedir);
		CoreTestListener ctl = new CoreTestListener();
		CryptoDataBaseImpl sec = new CryptoDataBaseImpl();
		TimeImpl time = new TimeImpl();
		DataBaseComImpl comdb = new DataBaseComImpl(c);
		comdb.setStore(store);
		comdb.addEventInterface(ctl);
		comdb.setSecurity(sec);
		comdb.setTime(time);
		CryptoComImpl cryptcom = new CryptoComImpl();
		SimpleConnector con = new SimpleConnector(false, "", 0);
		SimpleServerSocket server = new SimpleServerSocket(new ServerSocket(port));
		ComConnectionImpl imp = new ComConnectionImpl(c, comdb, cryptcom, ctl, basedir + File.separator + "tmp", server, con, false);
		c.setComConnector(imp);
		c.setComDataBase(comdb);
		c.addEventInterface(ctl);
		c.setSecurity(sec);
		c.setUserDataBase(store);
		c.setTime(time);
		return c;
	}
	
	public File createTempFile0(long filename) {
		try {
			File f = File.createTempFile("reffile", ".dat");
			FileOutputStream fos = new FileOutputStream(f);
			PrintWriter pw = new PrintWriter(fos);
			pw.println("This is a test reference file.");
			pw.println("Reference number: " + filename);
			pw.close();
			return f;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public File createMessageFile0(long filename) {
		try {
			File f = File.createTempFile("msgfile", ".dat");
			FileOutputStream fos = new FileOutputStream(f);
			PrintWriter pw = new PrintWriter(fos);
			pw.println("This is a test message file.");
			pw.println("Reference number: " + filename);
			pw.close();
			return f;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	@Test
	public void doTest() throws IOException {
		FileUtils.deleteDir("coretmp0");
		FileUtils.deleteDir("coretmp1");
		Core c0 = buildCore("coretmp0", 8845);
		Core c1 = buildCore("coretmp1", 8846);
		c0.generateNewKeys();
		c1.generateNewKeys();
		c0.setMyLocation("localhost:8845");
		c1.setMyLocation("localhost:8846");
		c0.setMyIntroduction("Hello I am localhost 8845");
		c1.setMyIntroduction("Hello I am localhost 8846");
		Peer p0 = c0.getMyPeerData();
		Peer p1 = c1.getMyPeerData();
		System.out.println("::p1:: " + p1.getLocation() + " sig: " + p1.getLocationSignature());
		c0.signPeer(p1);
		//c1.signPeer(p0);
		
		c0.updatePeers();
		c1.updatePeers();
		
		c1.addLocalFile(this.createTempFile0(10L), this.createMessageFile0(10L));
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		long backtime = (new Date()).getTime() - 60000L;
		List<LocalPost> lst = c1.getPosts(new Date(backtime));
		assertEquals(lst.size(), 1);

		System.out.println("============ signPeer p0 ===============");
		c1.signPeer(p0);
		System.out.println("============ c0.updatePosts() ===============");
		c0.updatePosts();

		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.println("============ Get our file references ===============");

		backtime = (new Date()).getTime() - 60000L;
		lst = c0.getPosts(new Date(backtime));
		assertEquals(lst.size(), 1);  //BROKEN HERE!
		
		System.out.println("============ Download the file reference ===============");

		LocalPost lp = lst.get(0);
		c0.downloadFile(lp.getPost().getFileReferenceDigest());

		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.println("============ c1.updatePosts() ===============");
		c1.updatePosts();
		
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}
