package vandy.mooc.model.services;

import vandy.mooc.common.DownloadUtils;
import vandy.mooc.common.LifecycleLoggingService;
import vandy.mooc.model.aidl.DownloadRequest;
import vandy.mooc.model.aidl.DownloadResults;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.IBinder;
import android.os.RemoteException;

/**
 * This class handles downloads using asynchronous AIDL interactions.
 * The component that binds to this service should receive an
 * IBinder. This IBinder should be an instance of DownloadRequest,
 * which extends IBinder. The component can then interact with this
 * service by making normal calls on the DownloadRequest
 * object. Specifically, the component can ask this service to
 * download an image, passing in a DownloadResults object.  Once the
 * download is finished, this service should send the pathname of the
 * downloaded file back to the calling component by calling sendPath()
 * on the DownloadResults object.
 *  
 * AIDL is an example of the Broker Pattern, in which all interprocess
 * communication details are hidden behind the AIDL interfaces.
 */
public class DownloadBoundServiceAsync 
       extends LifecycleLoggingService {
    /**
     * Make an explicit Intent that will start this service when
     * passed to bindService().
     *
     * @param context		The context of the calling component.
     */
    public static Intent makeIntent(Context context) {
        // Create an explicit Intent and return it to the caller.
        return new Intent(context,
                          DownloadBoundServiceAsync.class);		
    }

    /**
     * The concrete implementation of the AIDL Interface
     * DownloadRequest.  We extend the Stub class, which implements
     * DownloadRequest, so that Android can properly handle calls
     * across process boundaries.
     * 
     * This implementation plays the role of Invoker in the Broker
     * Pattern.
     */
    DownloadRequest.Stub mDownloadRequestImpl =
        new DownloadRequest.Stub() {
            /**
             * Download the image at the given Uri and return a
             * pathname to the file on the Android file system by
             * calling the sendPath() method on the provided Results
             * 
             * Use the methods defined in DownloadUtils for code brevity.
             */
            @Override
            public void downloadImage(Uri uri,
                                      DownloadResults results)
                throws RemoteException {
                // Download the file using the appropriate helper
                // method in DownloadUtils and then send the pathname
                // back to the client via the Results object.
                results.sendPath(DownloadUtils.downloadFile
                                  (DownloadBoundServiceAsync.this,
                                   uri));
            }
	};
	
    /**
     * Called when a component calls bindService() with the proper
     * intent.  Return the concrete implementation of DownloadRequest
     * cast as an IBinder.
     */
    @Override
    public IBinder onBind(Intent intent) {
        return mDownloadRequestImpl;
    }
}
