/*
 * Copyright (C) 2011 Google Inc.
 * Licensed to The Android Open Source Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.ex.photo;

import android.app.Activity;
import android.content.ContentProvider;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;

import com.android.ex.photo.fragments.PhotoViewFragment;

/**
 * Build intents to start app activities
 */

public class Intents {
    // Intent extras
    public static final String EXTRA_PHOTO_INDEX = "photo_index";
    public static final String EXTRA_INITIAL_PHOTO_URI = "initial_photo_uri";
    public static final String EXTRA_PHOTOS_URI = "photos_uri";
    public static final String EXTRA_RESOLVED_PHOTO_URI = "resolved_photo_uri";
    public static final String EXTRA_PROJECTION = "projection";
    public static final String EXTRA_THUMBNAIL_URI = "thumbnail_uri";
    public static final String EXTRA_MAX_INITIAL_SCALE = "max_scale";
    public static final String EXTRA_WATCH_NETWORK = "watch_network";
    public static final String EXTRA_ENABLE_TIMER_LIGHTS_OUT = "enable_timer_lights_out";


    // Parameters affecting the intro/exit animation
    public static final String EXTRA_SCALE_UP_ANIMATION = "scale_up_animation";
    public static final String EXTRA_ANIMATION_START_X = "start_x_extra";
    public static final String EXTRA_ANIMATION_START_Y = "start_y_extra";
    public static final String EXTRA_ANIMATION_START_WIDTH = "start_width_extra";
    public static final String EXTRA_ANIMATION_START_HEIGHT = "start_height_extra";

    // Parameters affecting the display and features
    public static final String EXTRA_ACTION_BAR_HIDDEN_INITIALLY = "action_bar_hidden_initially";
    public static final String EXTRA_DISPLAY_THUMBS_FULLSCREEN = "display_thumbs_fullscreen";

    /**
     * Gets a photo view intent builder to display the photos from phone activity.
     *
     * @param context The context
     * @return The intent builder
     */
    public static PhotoViewIntentBuilder newPhotoViewActivityIntentBuilder(Context context) {
        return new PhotoViewIntentBuilder(context, PhotoViewActivity.class);
    }

    /**
     * Gets a photo view intent builder to display the photo view fragment
     *
     * @param context The context
     * @return The intent builder
     */
    public static PhotoViewIntentBuilder newPhotoViewFragmentIntentBuilder(Context context) {
        return newPhotoViewFragmentIntentBuilder(context, PhotoViewFragment.class);
    }

    /**
     * Gets a photo view intent builder to display the photo view fragment with a custom fragment
     * subclass.
     *
     * @param context The context
     * @param clazz Subclass of PhotoViewFragment to use
     * @return The intent builder
     */
    public static PhotoViewIntentBuilder newPhotoViewFragmentIntentBuilder(Context context,
            Class<? extends PhotoViewFragment> clazz) {
        return new PhotoViewIntentBuilder(context, clazz);
    }

    /** Gets a new photo view intent builder */
    public static PhotoViewIntentBuilder newPhotoViewIntentBuilder(
            Context context, Class<? extends Activity> cls) {
        return new PhotoViewIntentBuilder(context, cls);
    }

    /** Gets a new photo view intent builder */
    public static PhotoViewIntentBuilder newPhotoViewIntentBuilder(
            Context context, String activityName) {
        return new PhotoViewIntentBuilder(context, activityName);
    }

    /** Builder to create a photo view intent */
    public static class PhotoViewIntentBuilder {
        private final Intent mIntent;

        /** The index of the photo to show */
        private Integer mPhotoIndex;
        /** The URI of the initial photo to show */
        private String mInitialPhotoUri;
        /** The URI of the initial thumbnail to show */
        private String mInitialThumbnailUri;
        /** The URI of the group of photos to display */
        private String mPhotosUri;
        /** The URL of the photo to display */
        private String mResolvedPhotoUri;
        /** The projection for the query to use; optional */
        private String[] mProjection;
        /** The URI of a thumbnail of the photo to display */
        private String mThumbnailUri;
        /** The maximum scale to display images at before  */
        private Float mMaxInitialScale;
        /** True if lights out should automatically be invoked on a timer basis */
        private boolean mEnableTimerLightsOut;
        /**
         * True if the PhotoViewFragments should watch for network changes to restart their loaders
         */
        private boolean mWatchNetwork;
        /** true we want to run the image scale animation */
        private boolean mScaleAnimation;
        /** The parameters for performing the scale up/scale down animations
         * upon enter and exit. StartX and StartY represent the screen coordinates
         * of the upper left corner of the start rectangle, startWidth and startHeight
         * represent the width and height of the start rectangle.
         */
        private int mStartX;
        private int mStartY;
        private int mStartWidth;
        private int mStartHeight;

        private boolean mActionBarHiddenInitially;
        private boolean mDisplayFullScreenThumbs;

        private PhotoViewIntentBuilder(Context context, Class<?> cls) {
            mIntent = new Intent(context, cls);
            initialize();
        }

        private PhotoViewIntentBuilder(Context context, String activityName) {
            mIntent = new Intent();
            mIntent.setClassName(context, activityName);
            initialize();
        }

        private void initialize() {
            mScaleAnimation = false;
            mActionBarHiddenInitially = false;
            mDisplayFullScreenThumbs = false;
            mEnableTimerLightsOut = true;
        }

        /** Sets auto lights out */
        public PhotoViewIntentBuilder setEnableTimerLightsOut(boolean enable) {
            mEnableTimerLightsOut = enable;
            return this;
        }

        /** Sets the photo index */
        public PhotoViewIntentBuilder setPhotoIndex(Integer photoIndex) {
            mPhotoIndex = photoIndex;
            return this;
        }

        /** Sets the initial photo URI */
        public PhotoViewIntentBuilder setInitialPhotoUri(String initialPhotoUri) {
            mInitialPhotoUri = initialPhotoUri;
            return this;
        }

        /** Sets the photos URI */
        public PhotoViewIntentBuilder setPhotosUri(String photosUri) {
            mPhotosUri = photosUri;
            return this;
        }

        /** Sets the query projection */
        public PhotoViewIntentBuilder setProjection(String[] projection) {
            mProjection = projection;
            return this;
        }

        /** Sets the resolved photo URI. This method is for the case
         *  where the URI given to {@link PhotoViewActivity} points directly
         *  to a single image and does not need to be resolved via a query
         *  to the {@link ContentProvider}. If this value is set, it supersedes
         *  {@link #setPhotosUri(String)}. */
        public PhotoViewIntentBuilder setResolvedPhotoUri(String resolvedPhotoUri) {
            mResolvedPhotoUri = resolvedPhotoUri;
            return this;
        }

        /**
         * Sets the URI for a thumbnail preview of the photo.
         */
        public PhotoViewIntentBuilder setThumbnailUri(String thumbnailUri) {
            mThumbnailUri = thumbnailUri;
            return this;
        }

        /**
         * Sets the maximum scale which an image is initially displayed at
         */
        public PhotoViewIntentBuilder setMaxInitialScale(float maxScale) {
            mMaxInitialScale = maxScale;
            return this;
        }

        /**
         * Enable watching the network for connectivity changes.
         *
         * When a change is detected, bitmap loaders will be restarted if required.
         */
        public PhotoViewIntentBuilder watchNetworkConnectivityChanges() {
            mWatchNetwork = true;
            return this;
        }

        /**
         * Enable a scale animation that animates the initial photo URI passed in using
         * {@link #setInitialPhotoUri}.
         *
         * Note: To avoid janky transitions, particularly when exiting the photoviewer, ensure the
         * following system UI flags are set on the root view of the relying app's activity
         * (via @{link View.setSystemUiVisibility(int)}):
         *     {@code View.SYSTEM_UI_FLAG_VISIBLE | View.SYSTEM_UI_FLAG_LAYOUT_STABLE}
         * As well, client should ensure {@code android:fitsSystemWindows} is set on the root
         * content view.
         */
        public PhotoViewIntentBuilder setScaleAnimation(int startX, int startY,
                int startWidth, int startHeight) {
            mScaleAnimation = true;
            mStartX = startX;
            mStartY = startY;
            mStartWidth = startWidth;
            mStartHeight = startHeight;
            return this;
        }

        // If this option is turned on, then the photoViewer will be initially
        // displayed with the action bar hidden. This is as opposed to the default
        // behavior, where the actionBar is initially shown.
        public PhotoViewIntentBuilder setActionBarHiddenInitially(
                boolean actionBarHiddenInitially) {
            mActionBarHiddenInitially = actionBarHiddenInitially;
            return this;
        }

        // If this option is turned on, then the small, lo-res thumbnail will
        // be scaled up to the maximum size to cover as much of the screen as
        // possible while still maintaining the correct aspect ratio. This means
        // that the image may appear blurry until the the full-res image is
        // loaded.
        // This is as opposed to the default behavior, where only part of the
        // thumbnail is displayed in a small view in the center of the screen,
        // and a loading spinner is displayed until the full-res image is loaded.
        public PhotoViewIntentBuilder setDisplayThumbsFullScreen(
                boolean displayFullScreenThumbs) {
            mDisplayFullScreenThumbs = displayFullScreenThumbs;
            return this;
        }

        /** Build the intent */
        public Intent build() {
            mIntent.setAction(Intent.ACTION_VIEW);

            // In Lollipop, each list of photos should appear as a document in the "Recents"
            // list. In earlier versions, this flag was Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET.
            mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT
                    // FLAG_ACTIVITY_CLEAR_TOP is needed for the case where the app tries to
                    // display a different photo while there is an existing activity instance
                    // for that list of photos. Since the initial photo is specified as an
                    // extra, without FLAG_ACTIVITY_CLEAR_TOP, the activity instance would
                    // just get restarted and it would display whatever photo it was last
                    // displaying. FLAG_ACTIVITY_CLEAR_TOP causes a new instance to be created,
                    // and it will display the new initial photo.
                    | Intent.FLAG_ACTIVITY_CLEAR_TOP);

            if (mPhotoIndex != null) {
                mIntent.putExtra(EXTRA_PHOTO_INDEX, (int) mPhotoIndex);
            }

            if (mInitialPhotoUri != null) {
                mIntent.putExtra(EXTRA_INITIAL_PHOTO_URI, mInitialPhotoUri);
            }

            if (mInitialPhotoUri != null && mPhotoIndex != null) {
                throw new IllegalStateException(
                        "specified both photo index and photo uri");
            }

            if (mPhotosUri != null) {
                mIntent.putExtra(EXTRA_PHOTOS_URI, mPhotosUri);
                mIntent.setData(Uri.parse(mPhotosUri));
            }

            if (mResolvedPhotoUri != null) {
                mIntent.putExtra(EXTRA_RESOLVED_PHOTO_URI, mResolvedPhotoUri);
            }

            if (mProjection != null) {
                mIntent.putExtra(EXTRA_PROJECTION, mProjection);
            }

            if (mThumbnailUri != null) {
                mIntent.putExtra(EXTRA_THUMBNAIL_URI, mThumbnailUri);
            }

            if (mMaxInitialScale != null) {
                mIntent.putExtra(EXTRA_MAX_INITIAL_SCALE, mMaxInitialScale);
            }

            mIntent.putExtra(EXTRA_WATCH_NETWORK, mWatchNetwork);

            mIntent.putExtra(EXTRA_SCALE_UP_ANIMATION, mScaleAnimation);
            if (mScaleAnimation) {
                mIntent.putExtra(EXTRA_ANIMATION_START_X, mStartX);
                mIntent.putExtra(EXTRA_ANIMATION_START_Y, mStartY);
                mIntent.putExtra(EXTRA_ANIMATION_START_WIDTH, mStartWidth);
                mIntent.putExtra(EXTRA_ANIMATION_START_HEIGHT, mStartHeight);
            }

            mIntent.putExtra(EXTRA_ACTION_BAR_HIDDEN_INITIALLY, mActionBarHiddenInitially);
            mIntent.putExtra(EXTRA_DISPLAY_THUMBS_FULLSCREEN, mDisplayFullScreenThumbs);
            mIntent.putExtra(EXTRA_ENABLE_TIMER_LIGHTS_OUT, mEnableTimerLightsOut);
            return mIntent;
        }
    }
}
