// This code grabbed (then modified) from:
//
// http://getablogger.blogspot.com/2008/01/android-how-to-post-file-to-php-server.html
//
// The idea of using this class is to run a simple PHP file uploader on the
// server and upload images via http (which lets me use existing technology
// rather than building a custom server to run on the host).

package lan.my.zooty.andyscan;

import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import android.util.Log;

public class PictureUploader implements Runnable {

   URL connectURL;
   String responseString;
   String fileName;
   byte[] jpegData;
   String Tag="Preview";

   // I get a byte[] buffer from the camera callback when I take a picture,
   // so just pass that buffer to the uploader along with the name I want to
   // give the file when it is uploaded along with the URL for the web
   // server where I'll upload it.

   PictureUploader(String urlString, String fileName, byte[] data) {
      Log.i(Tag,"In PictureUploader constructor");
      try {
         connectURL = new URL(urlString);
      } catch(Exception ex){
         Log.i(Tag,"MALFORMATED URL");
      }
      this.fileName = fileName;
      jpegData = data;
   }

   // Open the web server and upload the file in the separate thread.

   public void run() {
      Log.i(Tag, "In PictureUploader run()");
      String lineEnd = "\r\n";
      String twoHyphens = "--";
      String boundary = "*****14cac5ad-6280-4a5c-b012-bdfcc73883ac*****";
      try {

         //------------------ CLIENT REQUEST

         Log.i(Tag,"Starting upload");

         // Open a HTTP connection to the URL

         HttpURLConnection conn = (HttpURLConnection)connectURL.openConnection();

         // Allow Inputs
         conn.setDoInput(true);

         // Allow Outputs
         conn.setDoOutput(true);

         // Don't use a cached copy.
         conn.setUseCaches(false);

         // Some experimentation was required to discover this, but if I
         // want to used fixed streaming mode (which should avoid having to
         // make extra copies of the data to discover the size), the number
         // I need to pass to setFixedLengthStreamingMode() is the total
         // size of everything I'm planning to write() for this upload
         // request.  So, build prefix and suffix strings to determine the
         // length then write everything out to the connection after setting
         // the fixed length mode. NOTE: This code is probably wrong, since
         // I should be doing something about possible unicode filenames
         // getting messed up by writeBytes() tossing all but the low 8
         // bits. (But I don't know what I should be doing instead :-).

         String prefix = twoHyphens + boundary + lineEnd +
            "Content-Disposition: form-data; name=\"userfile\";filename=\"" +
            fileName +"\"" + lineEnd +
            "Content-Type: image/jpeg" + lineEnd +
            lineEnd;

         String suffix = lineEnd +
            twoHyphens + boundary + twoHyphens + lineEnd;

         conn.setFixedLengthStreamingMode(
            prefix.length() + jpegData.length + suffix.length());

         // Use a post method.
         conn.setRequestMethod("POST");

         conn.setRequestProperty("Connection", "Keep-Alive");

         conn.setRequestProperty("Content-Type",
                                 "multipart/form-data;boundary="+boundary);

         DataOutputStream dos = new DataOutputStream( conn.getOutputStream() );

         dos.writeBytes(prefix);

         Log.i(Tag,"Headers are written");

         dos.write(jpegData, 0, jpegData.length);

         // send multipart form data necesssary after file data...

         dos.writeBytes(suffix);

         // close streams

         Log.i(Tag,"File is written");
         dos.flush();

         InputStream is = conn.getInputStream();

         // retrieve the response from server

         int ch;

         StringBuffer b = new StringBuffer();
         while( ( ch = is.read() ) != -1 ){
            b.append( (char)ch );
         }
         String s=b.toString(); 
         Log.i("Response",s);
         dos.close();
      } catch (MalformedURLException ex) {
         Log.e(Tag, "error: " + ex.getMessage(), ex);
      } catch (IOException ioe) {
         Log.e(Tag, "error: " + ioe.getMessage(), ioe);
      }

      // Perhaps it would be advisable to tell the main activity I finished the
      // upload and it is safe to take another picture (though I suspect the
      // uploads should always take less time than fooling with the page
      // turning).
   }
}
