// ------------------------------------------------------------------------------
// Copyright (c) 2014 Microsoft Corporation
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
// ------------------------------------------------------------------------------

package com.microsoft.live.sample.skydrive;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

import org.json.JSONArray;
import org.json.JSONObject;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnDismissListener;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.view.Display;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.MediaController;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.VideoView;

import com.microsoft.live.LiveConnectClient;
import com.microsoft.live.LiveDownloadOperation;
import com.microsoft.live.LiveDownloadOperationListener;
import com.microsoft.live.LiveOperation;
import com.microsoft.live.LiveOperationException;
import com.microsoft.live.LiveOperationListener;
import com.microsoft.live.LiveUploadOperationListener;
import com.microsoft.live.sample.LiveSdkSampleApplication;
import com.microsoft.live.sample.R;
import com.microsoft.live.sample.skydrive.SkyDriveObject.Visitor;
import com.microsoft.live.sample.skydrive.SkyDrivePhoto.Image;
import com.microsoft.live.sample.util.FilePicker;
import com.microsoft.live.sample.util.JsonKeys;

public class SkyDriveActivity extends ListActivity {
    private class NewFolderDialog extends Dialog {
        public NewFolderDialog(Context context) {
            super(context);
        }

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.create_folder);
            setTitle("New Folder");

            final EditText name = (EditText) findViewById(R.id.nameEditText);
            final EditText description = (EditText) findViewById(R.id.descriptionEditText);

            findViewById(R.id.saveButton).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Map<String, String> folder = new HashMap<String, String>();
                    folder.put(JsonKeys.NAME, name.getText().toString());
                    folder.put(JsonKeys.DESCRIPTION, description.getText().toString());

                    final ProgressDialog progressDialog =
                            showProgressDialog("", "Saving. Please wait...", true);
                    progressDialog.show();

                    mClient.postAsync(mCurrentFolderId,
                                      new JSONObject(folder),
                                      new LiveOperationListener() {
                        @Override
                        public void onError(LiveOperationException exception, LiveOperation operation) {
                            progressDialog.dismiss();
                            showToast(exception.getMessage());
                        }

                        @Override
                        public void onComplete(LiveOperation operation) {
                            progressDialog.dismiss();

                            JSONObject result = operation.getResult();
                            if (result.has(JsonKeys.ERROR)) {
                                JSONObject error = result.optJSONObject(JsonKeys.ERROR);
                                String message = error.optString(JsonKeys.MESSAGE);
                                String code = error.optString(JsonKeys.CODE);
                                showToast(code + ":" + message);
                            } else {
                                dismiss();
                                loadFolder(mCurrentFolderId);
                            }
                        }
                    });
                }
            });

            findViewById(R.id.cancelButton).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    dismiss();
                }
            });
        }
    }

    private class PlayAudioDialog extends Dialog {
        private final SkyDriveAudio mAudio;
        private MediaPlayer mPlayer;
        private TextView mPlayerStatus;

        public PlayAudioDialog(Context context, SkyDriveAudio audio) {
            super(context);
            assert audio != null;
            mAudio = audio;
            mPlayer = new MediaPlayer();
        }

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setTitle(mAudio.getName());

            mPlayerStatus = new TextView(getContext());
            mPlayerStatus.setText("Buffering...");
            addContentView(mPlayerStatus,
                           new LayoutParams(LayoutParams.WRAP_CONTENT,
                                            LayoutParams.WRAP_CONTENT));

            mPlayer.setOnPreparedListener(new OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    mPlayerStatus.setText("Playing...");
                    mPlayer.start();
                }
            });

            mPlayer.setOnCompletionListener(new OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    mPlayerStatus.setText("Finished playing.");
                }
            });

            try {
                mPlayer.setDataSource(mAudio.getSource());
                mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                mPlayer.prepareAsync();
            } catch (IllegalArgumentException e) {
                showToast(e.getMessage());
                return;
            } catch (IllegalStateException e) {
                showToast(e.getMessage());
                return;
            } catch (IOException e) {
                showToast(e.getMessage());
                return;
            }
        }

        @Override
        protected void onStop() {
            super.onStop();
            mPlayer.stop();
            mPlayer.release();
            mPlayer = null;
        }
    }

    /**
     * Supported media formats can be found
     * <a href="http://developer.android.com/guide/appendix/media-formats.html">here</a>
     */
    private class PlayVideoDialog extends Dialog {
        private final SkyDriveVideo mVideo;
        private VideoView mVideoHolder;

        public PlayVideoDialog(Context context, SkyDriveVideo video) {
            super(context);
            assert video != null;
            mVideo = video;
        }

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setTitle(mVideo.getName());

            mVideoHolder = new VideoView(getContext());
            mVideoHolder.setMediaController(new MediaController(getContext()));
            mVideoHolder.setVideoURI(Uri.parse(mVideo.getSource()));
            addContentView(mVideoHolder,
                           new LayoutParams(LayoutParams.WRAP_CONTENT,
                                            LayoutParams.WRAP_CONTENT));
        }

        @Override
        protected void onStart() {
            super.onStart();
            mVideoHolder.start();
        }
    }

    private class SkyDriveListAdapter extends BaseAdapter {
        private final LayoutInflater mInflater;
        private final ArrayList<SkyDriveObject> mSkyDriveObjs;
        private View mView;

        public SkyDriveListAdapter(Context context) {
            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            mSkyDriveObjs = new ArrayList<SkyDriveObject>();
        }

        /**
         * @return The underlying array of the class. If changes are made to this object and you
         * want them to be seen, call {@link #notifyDataSetChanged()}.
         */
        public ArrayList<SkyDriveObject> getSkyDriveObjs() {
            return mSkyDriveObjs;
        }

        @Override
        public int getCount() {
            return mSkyDriveObjs.size();
        }

        @Override
        public SkyDriveObject getItem(int position) {
            return mSkyDriveObjs.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        // Note: This implementation of the ListAdapter.getView(...) forces a download of thumb-nails when retrieving
        // views, this is not a good solution in regards to CPU time and network band-width.
        @Override
        public View getView(int position, View convertView, final ViewGroup parent) {
            SkyDriveObject skyDriveObj = getItem(position);
            mView = convertView != null ? convertView : null;

            skyDriveObj.accept(new Visitor() {
                @Override
                public void visit(SkyDriveVideo video) {
                    if (mView == null) {
                        mView = inflateNewSkyDriveListItem();
                    }

                    setIcon(R.drawable.video_x_generic);
                    setName(video);
                    setDescription(video);
                }

                @Override
                public void visit(SkyDriveFile file) {
                    if (mView == null) {
                        mView = inflateNewSkyDriveListItem();
                    }

                    setIcon(R.drawable.text_x_preview);
                    setName(file);
                    setDescription(file);
                }

                @Override
                public void visit(SkyDriveFolder folder) {
                    if (mView == null) {
                        mView = inflateNewSkyDriveListItem();
                    }

                    setIcon(R.drawable.folder);
                    setName(folder);
                    setDescription(folder);
                }

                @Override
                public void visit(SkyDrivePhoto photo) {
                    if (mView == null) {
                        mView = inflateNewSkyDriveListItem();
                    }

                    setIcon(R.drawable.image_x_generic);
                    setName(photo);
                    setDescription(photo);

                    // Try to find a smaller/thumbnail and use that source
                    String thumbnailSource = null;
                    String smallSource = null;
                    for (Image image : photo.getImages()) {
                        if (image.getType().equals("small")) {
                            smallSource = image.getSource();
                        } else if (image.getType().equals("thumbnail")) {
                            thumbnailSource = image.getSource();
                        }
                    }

                    String source = thumbnailSource != null ? thumbnailSource :
                                    smallSource != null ? smallSource : null;

                    // if we do not have a thumbnail or small image, just leave.
                    if (source == null) {
                        return;
                    }

                    // Since we are doing async calls and mView is constantly changing,
                    // we need to hold on to this reference.
                    final View v = mView;
                    new AsyncTask<String, Long, Bitmap>() {
                        @Override
                        protected Bitmap doInBackground(String... params) {
                            try {
                                // Download the thumb nail image
                                LiveDownloadOperation operation = mClient.download(params[0]);

                                // Make sure we don't burn up memory for all of
                                // these thumb nails that are transient
                                BitmapFactory.Options options = new BitmapFactory.Options();
                                options.inPurgeable = true;
                                return BitmapFactory.decodeStream(operation.getStream(), (Rect)null, options);
                            } catch (Exception e) {
                                showToast(e.getMessage());
                                return null;
                            }
                        }

                        @Override
                        protected void onPostExecute(Bitmap result) {
                            ImageView imgView = (ImageView)v.findViewById(R.id.skyDriveItemIcon);
                            imgView.setImageBitmap(result);
                        }
                    }.execute(source);
                }

                @Override
                public void visit(SkyDriveAlbum album) {
                    if (mView == null) {
                        mView = inflateNewSkyDriveListItem();
                    }

                    setIcon(R.drawable.folder_image);
                    setName(album);
                    setDescription(album);
                }

                @Override
                public void visit(SkyDriveAudio audio) {
                    if (mView == null) {
                        mView = inflateNewSkyDriveListItem();
                    }

                    setIcon(R.drawable.audio_x_generic);
                    setName(audio);
                    setDescription(audio);
                }

                private void setName(SkyDriveObject skyDriveObj) {
                    TextView tv = (TextView) mView.findViewById(R.id.nameTextView);
                    tv.setText(skyDriveObj.getName());
                }

                private void setDescription(SkyDriveObject skyDriveObj) {
                    String description = skyDriveObj.getDescription();
                    if (description == null) {
                        description = "No description.";
                    }

                    TextView tv = (TextView) mView.findViewById(R.id.descriptionTextView);
                    tv.setText(description);
                }

                private View inflateNewSkyDriveListItem() {
                    return mInflater.inflate(R.layout.skydrive_list_item, parent, false);
                }

                private void setIcon(int iconResId) {
                    ImageView img = (ImageView) mView.findViewById(R.id.skyDriveItemIcon);
                    img.setImageResource(iconResId);
                }
            });


            return mView;
        }
    }

    private class ViewPhotoDialog extends Dialog {
        private final SkyDrivePhoto mPhoto;

        public ViewPhotoDialog(Context context, SkyDrivePhoto photo) {
            super(context);
            assert photo != null;
            mPhoto = photo;
        }

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setTitle(mPhoto.getName());
            final ImageView imgView = new ImageView(getContext());
            addContentView(imgView,
                           new LayoutParams(LayoutParams.WRAP_CONTENT,
                                            LayoutParams.WRAP_CONTENT));

            mClient.downloadAsync(mPhoto.getSource(), new LiveDownloadOperationListener() {
                @Override
                public void onDownloadProgress(int totalBytes,
                                               int bytesRemaining,
                                               LiveDownloadOperation operation) {
                }

                @Override
                public void onDownloadFailed(LiveOperationException exception,
                                             LiveDownloadOperation operation) {
                    showToast(exception.getMessage());
                }

                @Override
                public void onDownloadCompleted(LiveDownloadOperation operation) {
                    new AsyncTask<LiveDownloadOperation, Long, Bitmap>() {
                        @Override
                        protected Bitmap doInBackground(LiveDownloadOperation... params) {
                            return extractScaledBitmap(mPhoto, params[0].getStream());
                        }

                        @Override
                        protected void onPostExecute(Bitmap result) {
                            imgView.setImageBitmap(result);
                        }
                    }.execute(operation);
                }
            });
        }
    }

    public static final String EXTRA_PATH = "path";

    private static final int DIALOG_DOWNLOAD_ID = 0;
    private static final String HOME_FOLDER = "me/skydrive";

    private LiveConnectClient mClient;
    private SkyDriveListAdapter mPhotoAdapter;
    private String mCurrentFolderId;
    private Stack<String> mPrevFolderIds;

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == FilePicker.PICK_FILE_REQUEST) {
            if (resultCode == RESULT_OK) {
                String filePath = data.getStringExtra(FilePicker.EXTRA_FILE_PATH);

                if (TextUtils.isEmpty(filePath)) {
                    showToast("No file was choosen.");
                    return;
                }

                File file = new File(filePath);

                final ProgressDialog uploadProgressDialog =
                        new ProgressDialog(SkyDriveActivity.this);
                uploadProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                uploadProgressDialog.setMessage("Uploading...");
                uploadProgressDialog.setCancelable(true);
                uploadProgressDialog.show();

                final LiveOperation operation =
                        mClient.uploadAsync(mCurrentFolderId,
                                            file.getName(),
                                            file,
                                            new LiveUploadOperationListener() {
                    @Override
                    public void onUploadProgress(int totalBytes,
                                                 int bytesRemaining,
                                                 LiveOperation operation) {
                        int percentCompleted = computePrecentCompleted(totalBytes, bytesRemaining);

                        uploadProgressDialog.setProgress(percentCompleted);
                    }

                    @Override
                    public void onUploadFailed(LiveOperationException exception,
                                               LiveOperation operation) {
                        uploadProgressDialog.dismiss();
                        showToast(exception.getMessage());
                    }

                    @Override
                    public void onUploadCompleted(LiveOperation operation) {
                        uploadProgressDialog.dismiss();

                        JSONObject result = operation.getResult();
                        if (result.has(JsonKeys.ERROR)) {
                            JSONObject error = result.optJSONObject(JsonKeys.ERROR);
                            String message = error.optString(JsonKeys.MESSAGE);
                            String code = error.optString(JsonKeys.CODE);
                            showToast(code + ": " + message);
                            return;
                        }

                        loadFolder(mCurrentFolderId);
                    }
                });

                uploadProgressDialog.setOnCancelListener(new OnCancelListener() {
                    @Override
                    public void onCancel(DialogInterface dialog) {
                        operation.cancel();
                    }
                });
            }
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.skydrive);

        mPrevFolderIds = new Stack<String>();

        ListView lv = getListView();
        lv.setTextFilterEnabled(true);
        lv.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                SkyDriveObject skyDriveObj = (SkyDriveObject) parent.getItemAtPosition(position);

                skyDriveObj.accept(new Visitor() {
                    @Override
                    public void visit(SkyDriveAlbum album) {
                        mPrevFolderIds.push(mCurrentFolderId);
                        loadFolder(album.getId());
                    }

                    @Override
                    public void visit(SkyDrivePhoto photo) {
                        ViewPhotoDialog dialog =
                                new ViewPhotoDialog(SkyDriveActivity.this, photo);
                        dialog.setOwnerActivity(SkyDriveActivity.this);
                        dialog.show();
                    }

                    @Override
                    public void visit(SkyDriveFolder folder) {
                        mPrevFolderIds.push(mCurrentFolderId);
                        loadFolder(folder.getId());
                    }

                    @Override
                    public void visit(SkyDriveFile file) {
                        Bundle b = new Bundle();
                        b.putString(JsonKeys.ID, file.getId());
                        b.putString(JsonKeys.NAME, file.getName());
                        showDialog(DIALOG_DOWNLOAD_ID, b);
                    }

                    @Override
                    public void visit(SkyDriveVideo video) {
                        PlayVideoDialog dialog = new PlayVideoDialog(SkyDriveActivity.this, video);
                        dialog.setOwnerActivity(SkyDriveActivity.this);
                        dialog.show();
                    }

                    @Override
                    public void visit(SkyDriveAudio audio) {
                        PlayAudioDialog audioDialog =
                                new PlayAudioDialog(SkyDriveActivity.this, audio);
                        audioDialog.show();
                    }
                });
            }
        });

        LinearLayout layout = new LinearLayout(this);
        Button newFolderButton = new Button(this);
        newFolderButton.setText("New Folder");
        newFolderButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                NewFolderDialog dialog = new NewFolderDialog(SkyDriveActivity.this);
                dialog.setOwnerActivity(SkyDriveActivity.this);
                dialog.show();
            }
        });

        layout.addView(newFolderButton);

        Button uploadFileButton = new Button(this);
        uploadFileButton.setText("Upload File");
        uploadFileButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(), FilePicker.class);
                startActivityForResult(intent, FilePicker.PICK_FILE_REQUEST);
            }
        });

        layout.addView(uploadFileButton);
        lv.addHeaderView(layout);

        mPhotoAdapter = new SkyDriveListAdapter(this);
        setListAdapter(mPhotoAdapter);

        LiveSdkSampleApplication app = (LiveSdkSampleApplication) getApplication();
        mClient = app.getConnectClient();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            // if prev folders is empty, send the back button to the TabView activity.
            if (mPrevFolderIds.isEmpty()) {
                return false;
            }

            loadFolder(mPrevFolderIds.pop());
            return true;
        } else {
            return super.onKeyDown(keyCode, event);
        }
    }

    @Override
    protected Dialog onCreateDialog(final int id, final Bundle bundle) {
        Dialog dialog = null;
        switch (id) {
            case DIALOG_DOWNLOAD_ID: {
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setTitle("Download")
                       .setMessage("This file will be downloaded to the sdcard.")
                       .setPositiveButton("OK", new Dialog.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        final ProgressDialog progressDialog =
                                new ProgressDialog(SkyDriveActivity.this);
                        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                        progressDialog.setMessage("Downloading...");
                        progressDialog.setCancelable(true);
                        progressDialog.show();

                        String fileId = bundle.getString(JsonKeys.ID);
                        String name = bundle.getString(JsonKeys.NAME);

                        File file = new File(Environment.getExternalStorageDirectory(), name);

                        final LiveDownloadOperation operation =
                                mClient.downloadAsync(fileId + "/content",
                                                      file,
                                                      new LiveDownloadOperationListener() {
                            @Override
                            public void onDownloadProgress(int totalBytes,
                                                           int bytesRemaining,
                                                           LiveDownloadOperation operation) {
                                int percentCompleted =
                                        computePrecentCompleted(totalBytes, bytesRemaining);

                                progressDialog.setProgress(percentCompleted);
                            }

                            @Override
                            public void onDownloadFailed(LiveOperationException exception,
                                                         LiveDownloadOperation operation) {
                                progressDialog.dismiss();
                                showToast(exception.getMessage());
                            }

                            @Override
                            public void onDownloadCompleted(LiveDownloadOperation operation) {
                                progressDialog.dismiss();
                                showToast("File downloaded.");
                            }
                        });

                        progressDialog.setOnCancelListener(new OnCancelListener() {
                            @Override
                            public void onCancel(DialogInterface dialog) {
                                operation.cancel();
                            }
                        });
                    }
                }).setNegativeButton("Cancel", new Dialog.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                    }
                });

                dialog = builder.create();
                break;
            }
        }

        if (dialog != null) {
            dialog.setOnDismissListener(new OnDismissListener() {
                @Override
                public void onDismiss(DialogInterface dialog) {
                    removeDialog(id);
                }
            });
        }

        return dialog;
    }

    @Override
    protected void onStart() {
        super.onStart();
        loadFolder(HOME_FOLDER);
    }

    private void loadFolder(String folderId) {
        assert folderId != null;
        mCurrentFolderId = folderId;

        final ProgressDialog progressDialog =
                ProgressDialog.show(this, "", "Loading. Please wait...", true);

        mClient.getAsync(folderId + "/files", new LiveOperationListener() {
            @Override
            public void onComplete(LiveOperation operation) {
                progressDialog.dismiss();

                JSONObject result = operation.getResult();
                if (result.has(JsonKeys.ERROR)) {
                    JSONObject error = result.optJSONObject(JsonKeys.ERROR);
                    String message = error.optString(JsonKeys.MESSAGE);
                    String code = error.optString(JsonKeys.CODE);
                    showToast(code + ": " + message);
                    return;
                }

                ArrayList<SkyDriveObject> skyDriveObjs = mPhotoAdapter.getSkyDriveObjs();
                skyDriveObjs.clear();

                JSONArray data = result.optJSONArray(JsonKeys.DATA);
                for (int i = 0; i < data.length(); i++) {
                    SkyDriveObject skyDriveObj = SkyDriveObject.create(data.optJSONObject(i));
                    if (skyDriveObj != null) {
                        skyDriveObjs.add(skyDriveObj);
                    }
                }

                mPhotoAdapter.notifyDataSetChanged();
            }

            @Override
            public void onError(LiveOperationException exception, LiveOperation operation) {
                progressDialog.dismiss();

                showToast(exception.getMessage());
            }
        });
    }

    private void showToast(String message) {
        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
    }

    private int computePrecentCompleted(int totalBytes, int bytesRemaining) {
        return (int) (((float)(totalBytes - bytesRemaining)) / totalBytes * 100);
    }

    private ProgressDialog showProgressDialog(String title, String message, boolean indeterminate) {
        return ProgressDialog.show(this, title, message, indeterminate);
    }

    /**
     * Extract a photo from SkyDrive and creates a scaled bitmap according to the device resolution, this is needed to
     * prevent memory over-allocation that can cause some devices to crash when opening high-resolution pictures
     *
     * Note: this method should not be used for downloading photos, only for displaying photos on-screen
     *
