package com.parc.ccn.apps;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import javax.xml.stream.XMLStreamException;

import com.parc.ccn.Library;
import com.parc.ccn.config.ConfigurationException;
import com.parc.ccn.data.ContentName;
import com.parc.ccn.data.MalformedContentNameStringException;
import com.parc.ccn.library.CCNLibrary;
import com.parc.ccn.library.io.CCNOutputStream;
import com.parc.ccn.library.io.repo.RepositoryOutputStream;
import com.parc.ccn.library.profiles.VersioningProfile;

public class put_file {
	
	private static int BLOCK_SIZE = 8096;
	private static boolean rawMode = false;

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		int startArg = 0;
		if (args.length > 0 && args[0].equals("-raw")) {
			startArg++;
			rawMode = true;
		}
		if (args.length < startArg + 2) {
			usage();
			return;
		}
		
		try {
			// If we get one file name, put as the specific name given.
			// If we get more than one, put underneath the first as parent.
			// Ideally want to use newVersion to get latest version. Start
			// with random version.
			ContentName argName = ContentName.fromURI(args[startArg]);
			
			CCNLibrary library = CCNLibrary.open();
			
			if (args.length == (startArg + 2)) {
				
				File theFile = new File(args[startArg + 1]);
				if (!theFile.exists()) {
					System.out.println("No such file: " + args[startArg + 1]);
					usage();
					return;
				}
				Library.logger().info("put_file: putting file " + args[startArg + 1] + " bytes: " + theFile.length());
				
				ContentName versionedName = VersioningProfile.versionName(argName);
				CCNOutputStream ostream;
				if (rawMode)
					ostream = new CCNOutputStream(versionedName, library);
				else
					ostream = new RepositoryOutputStream(versionedName, library);
				do_write(ostream, theFile);
				
				System.out.println("Inserted file " + args[startArg + 1] + ".");
				System.exit(0);
			} else {
				for (int i=startArg + 1; i < args.length; ++i) {
					
					File theFile = new File(args[i]);
					if (!theFile.exists()) {
						System.out.println("No such file: " + args[i]);
						usage();
						return;
					}
					
					//FileOutputStream testOut = new FileOutputStream("put_file" + i + ".dat");
					//testOut.write(contents);
					//testOut.flush();
					//testOut.close();
					
					// put as child of name
					ContentName nodeName = ContentName.fromURI(argName, theFile.getName());
					
					// int version = new Random().nextInt(1000);
					// would be version = library.latestVersion(argName) + 1;
					CCNOutputStream ostream;
					ContentName versionedNodeName = VersioningProfile.versionName(nodeName);
					if (rawMode)
						ostream = new CCNOutputStream(versionedNodeName, library);
					else
						ostream = new RepositoryOutputStream(versionedNodeName, library);
					do_write(ostream, theFile);
					
					System.out.println("Inserted file " + args[i] + ".");
					
				}
			}
		} catch (ConfigurationException e) {
			System.out.println("Configuration exception in put: " + e.getMessage());
			e.printStackTrace();
		} catch (MalformedContentNameStringException e) {
			System.out.println("Malformed name: " + args[startArg] + " " + e.getMessage());
			e.printStackTrace();
		} catch (IOException e) {
			System.out.println("Cannot read file. " + e.getMessage());
			e.printStackTrace();
		} catch (XMLStreamException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	
	private static void do_write(CCNOutputStream ostream, File file) throws IOException {
		long time = System.currentTimeMillis();
		FileInputStream fis = new FileInputStream(file);
		int size = BLOCK_SIZE;
		byte [] buffer = new byte[BLOCK_SIZE];
		do {
			Library.logger().info("do_write: " + fis.available() + " bytes left.");
			if (size > fis.available())
				size = fis.available();
			if (size > 0) {
				fis.read(buffer, 0, size);
				ostream.write(buffer, 0, size);
				Library.logger().info("do_write: wrote " + size + " bytes.");
			}
		} while (fis.available() > 0);
		ostream.close();
		Library.logger().info("finished write: "+(System.currentTimeMillis() - time));
	}
	
	public static void usage() {
		System.out.println("usage: put_file [-raw] <ccnname> <filename> [<filename> ...]");
	}

}

@@ -454,32 +454,36 @@
 .repo.Repository
+File
 OutputStream;%0Aim
@@ -1771,32 +1771,36 @@
 = new Repository
+File
 OutputStream(ver
@@ -2806,16 +2806,20 @@
 pository
+File
 OutputSt
@@ -3691,16 +3691,35 @@
 K_SIZE;%0A
+%09%09int readLen = 0;%0A
 %09%09byte %5B
@@ -3757,14 +3757,15 @@
 ;%0A%09%09
+//
 do %7B%0A
-%09
 %09%09Li
@@ -3832,25 +3832,82 @@
  left.%22);%0A%09%09
-%09
+while((readLen = fis.read(buffer, 0, size)) != -1)%7B%09%0A%09%09%09//
 if (size %3E f
@@ -3925,16 +3925,18 @@
 e())%0A%09%09%09
+//
 %09size = 
@@ -3951,24 +3951,26 @@
 lable();%0A%09%09%09
+//
 if (size %3E 0
@@ -3976,16 +3976,18 @@
 0) %7B%0A%09%09%09
+//
 %09fis.rea
@@ -4009,16 +4009,18 @@
 ze);%0A%09%09%09
+//
 %09ostream
@@ -4045,16 +4045,53 @@
 size);%0A%09
+%09%09ostream.write(buffer, 0, readLen);%0A
 %09%09%09Libra
@@ -4148,22 +4148,98 @@
 es.%22);%0A%09
+%09%09Library.logger().info(%22do_write: %22 + fis.available() + %22 bytes left.%22);%0A
 %09%09%7D%0A%09%09
+//
 %7D while 

switch put_file to use a RepositoryFileOutputStream instead of a RepositoryOutputStream