/*
 * 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.fragments;

import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.android.ex.photo.Intents;
import com.android.ex.photo.PhotoViewCallbacks;
import com.android.ex.photo.PhotoViewCallbacks.CursorChangedListener;
import com.android.ex.photo.PhotoViewCallbacks.OnScreenListener;
import com.android.ex.photo.R;
import com.android.ex.photo.adapters.PhotoPagerAdapter;
import com.android.ex.photo.loaders.PhotoBitmapLoader;
import com.android.ex.photo.util.ImageUtils;
import com.android.ex.photo.views.PhotoView;
import com.android.ex.photo.views.ProgressBarWrapper;

/**
 * Displays a photo.
 */
public class PhotoViewFragment extends Fragment implements
        LoaderManager.LoaderCallbacks<Bitmap>,
        OnClickListener,
        OnScreenListener,
        CursorChangedListener {
    /**
     * Interface for components that are internally scrollable left-to-right.
     */
    public static interface HorizontallyScrollable {
        /**
         * Return {@code true} if the component needs to receive right-to-left
         * touch movements.
         *
         * @param origX the raw x coordinate of the initial touch
         * @param origY the raw y coordinate of the initial touch
         */

        public boolean interceptMoveLeft(float origX, float origY);

        /**
         * Return {@code true} if the component needs to receive left-to-right
         * touch movements.
         *
         * @param origX the raw x coordinate of the initial touch
         * @param origY the raw y coordinate of the initial touch
         */
        public boolean interceptMoveRight(float origX, float origY);
    }

    protected final static String STATE_INTENT_KEY =
            "com.android.mail.photo.fragments.PhotoViewFragment.INTENT";

    private final static String ARG_INTENT = "arg-intent";
    private final static String ARG_POSITION = "arg-position";
    private final static String ARG_SHOW_SPINNER = "arg-show-spinner";

    // Loader IDs
    protected final static int LOADER_ID_PHOTO = 1;
    protected final static int LOADER_ID_THUMBNAIL = 2;

    /** The size of the photo */
    public static Integer sPhotoSize;

    /** The URL of a photo to display */
    protected String mResolvedPhotoUri;
    protected String mThumbnailUri;
    /** The intent we were launched with */
    protected Intent mIntent;
    protected PhotoViewCallbacks mCallback;
    protected PhotoPagerAdapter mAdapter;

    protected PhotoView mPhotoView;
    protected ImageView mPhotoPreviewImage;
    protected TextView mEmptyText;
    protected ImageView mRetryButton;
    protected ProgressBarWrapper mPhotoProgressBar;

    protected int mPosition;

    /** Whether or not the fragment should make the photo full-screen */
    protected boolean mFullScreen;

    /** Whether or not this fragment will only show the loading spinner */
    protected boolean mOnlyShowSpinner;

    /** Whether or not the progress bar is showing valid information about the progress stated */
    protected boolean mProgressBarNeeded = true;

    protected View mPhotoPreviewAndProgress;
    protected boolean mThumbnailShown;

    /** Public no-arg constructor for allowing the framework to handle orientation changes */
    public PhotoViewFragment() {
        // Do nothing.
    }

    /**
     * Create a {@link PhotoViewFragment}.
     * @param intent
     * @param position
     * @param onlyShowSpinner
     */
    public static final PhotoViewFragment newInstance(
            Intent intent, int position, boolean onlyShowSpinner) {
        final Bundle b = new Bundle();
        b.putParcelable(ARG_INTENT, intent);
        b.putInt(ARG_POSITION, position);
        b.putBoolean(ARG_SHOW_SPINNER, onlyShowSpinner);
        final PhotoViewFragment f = new PhotoViewFragment();
        f.setArguments(b);
        return f;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mCallback = (PhotoViewCallbacks) getActivity();
        if (mCallback == null) {
            throw new IllegalArgumentException(
                    "Activity must be a derived class of PhotoViewActivity");
        }
        mAdapter = mCallback.getAdapter();
        if (mAdapter == null) {
            throw new IllegalStateException("Callback reported null adapter");
        }
        // Don't call until we've setup the entire view
        setViewVisibility();
    }

    @Override
    public void onDetach() {
        mCallback = null;
        super.onDetach();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (sPhotoSize == null) {
            final DisplayMetrics metrics = new DisplayMetrics();
            final WindowManager wm =
                    (WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE);
            final ImageUtils.ImageSize imageSize = ImageUtils.sUseImageSize;
            wm.getDefaultDisplay().getMetrics(metrics);
            switch (imageSize) {
                case EXTRA_SMALL:
                    // Use a photo that's 80% of the "small" size
                    sPhotoSize = (Math.min(metrics.heightPixels, metrics.widthPixels) * 800) / 1000;
                    break;
                case SMALL:
                    // Fall through.
                case NORMAL:
                    // Fall through.
                default:
                    sPhotoSize = Math.min(metrics.heightPixels, metrics.widthPixels);
                    break;
            }
        }

        final Bundle bundle = getArguments();
        if (bundle == null) {
            return;
        }
        mIntent = bundle.getParcelable(ARG_INTENT);
        mPosition = bundle.getInt(ARG_POSITION);
        mOnlyShowSpinner = bundle.getBoolean(ARG_SHOW_SPINNER);
        mProgressBarNeeded = true;

        if (savedInstanceState != null) {
            final Bundle state = savedInstanceState.getBundle(STATE_INTENT_KEY);
            if (state != null) {
                mIntent = new Intent().putExtras(state);
            }
        }

        if (mIntent != null) {
            mResolvedPhotoUri = mIntent.getStringExtra(Intents.EXTRA_RESOLVED_PHOTO_URI);
            mThumbnailUri = mIntent.getStringExtra(Intents.EXTRA_THUMBNAIL_URI);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        final View view = inflater.inflate(R.layout.photo_fragment_view, container, false);
        initializeView(view);
        return view;
    }

    protected void initializeView(View view) {
        mPhotoView = (PhotoView) view.findViewById(R.id.photo_view);
        mPhotoView.setMaxInitialScale(mIntent.getFloatExtra(Intents.EXTRA_MAX_INITIAL_SCALE, 1));
        mPhotoView.setOnClickListener(this);
        mPhotoView.setFullScreen(mFullScreen, false);
        mPhotoView.enableImageTransforms(false);

        mPhotoPreviewAndProgress = view.findViewById(R.id.photo_preview);
        mPhotoPreviewImage = (ImageView) view.findViewById(R.id.photo_preview_image);
        mThumbnailShown = false;
        final ProgressBar indeterminate =
                (ProgressBar) view.findViewById(R.id.indeterminate_progress);
        final ProgressBar determinate =
                (ProgressBar) view.findViewById(R.id.determinate_progress);
        mPhotoProgressBar = new ProgressBarWrapper(determinate, indeterminate, true);
        mEmptyText = (TextView) view.findViewById(R.id.empty_text);
        mRetryButton = (ImageView) view.findViewById(R.id.retry_button);
    }

    @Override
    public void onResume() {
        super.onResume();
        mCallback.addScreenListener(mPosition, this);
        mCallback.addCursorListener(this);

        if (!isPhotoBound()) {
            mProgressBarNeeded = true;
            mPhotoPreviewAndProgress.setVisibility(View.VISIBLE);

            getLoaderManager().initLoader(LOADER_ID_THUMBNAIL, null, this);
            getLoaderManager().initLoader(LOADER_ID_PHOTO, null, this);
        }
    }

    @Override
    public void onPause() {
        // Remove listeners
        mCallback.removeCursorListener(this);
        mCallback.removeScreenListener(mPosition);
        resetPhotoView();
        super.onPause();
    }

    @Override
    public void onDestroyView() {
        // Clean up views and other components
        if (mPhotoView != null) {
            mPhotoView.clear();
            mPhotoView = null;
        }
        super.onDestroyView();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        if (mIntent != null) {
            outState.putParcelable(STATE_INTENT_KEY, mIntent.getExtras());
        }
    }

    @Override
    public Loader<Bitmap> onCreateLoader(int id, Bundle args) {
        if(mOnlyShowSpinner) {
            return null;
        }
        switch (id) {
            case LOADER_ID_PHOTO:
                return new PhotoBitmapLoader(getActivity(), mResolvedPhotoUri);
            case LOADER_ID_THUMBNAIL:
                return new PhotoBitmapLoader(getActivity(), mThumbnailUri);
            default:
                return null;
        }
    }

    @Override
    public void onLoadFinished(Loader<Bitmap> loader, Bitmap data) {
        // If we don't have a view, the fragment has been paused. We'll get the cursor again later.
        if (getView() == null) {
            return;
        }

        // both loaders are started together, they may finish loading in such a
        // way that the thumbnail is displayed on top of the full image
        final int id = loader.getId();
        switch (id) {
            case LOADER_ID_THUMBNAIL:
                if (isPhotoBound()) {
                    // There is need to do anything with the thumbnail
                    // image, as the full size
                    // image is being shown.
                    return;
                }

                if (data == null) {
                    // no preview, show default
                    mPhotoPreviewImage.setImageResource(R.drawable.default_image);
                    mThumbnailShown = false;
                } else {
                    // show preview
                    mPhotoPreviewImage.setImageBitmap(data);
                    mThumbnailShown = true;
                }
                mPhotoPreviewImage.setVisibility(View.VISIBLE);
                mPhotoPreviewImage.setScaleType(ImageView.ScaleType.CENTER);
                enableImageTransforms(false);
                break;
            case LOADER_ID_PHOTO:
                bindPhoto(data);
                break;
            default:
                break;
        }

        if (mProgressBarNeeded == false) {
            // Hide the progress bar as it isn't needed anymore.
            mPhotoProgressBar.setVisibility(View.GONE);
        }

        if (data != null) {
            mCallback.onNewPhotoLoaded(mPosition);
        }
        setViewVisibility();
    }

    /**
     * Binds an image to the photo view.
     */
    private void bindPhoto(Bitmap bitmap) {
        if (bitmap != null) {
            if (mPhotoView != null) {
                mPhotoView.bindPhoto(bitmap);
            }
            enableImageTransforms(true);
            mPhotoPreviewAndProgress.setVisibility(View.GONE);
            mProgressBarNeeded = false;
        }
    }

    /**
     * Enable or disable image transformations. When transformations are enabled, this view
     * consumes all touch events.
     */
    public void enableImageTransforms(boolean enable) {
        mPhotoView.enableImageTransforms(enable);
    }

    /**
     * Resets the photo view to it's default state w/ no bound photo.
     */
    private void resetPhotoView() {
        if (mPhotoView != null) {
            mPhotoView.bindPhoto(null);
        }
    }

    @Override
    public void onLoaderReset(Loader<Bitmap> loader) {
        // Do nothing
    }

    @Override
    public void onClick(View v) {
        mCallback.toggleFullScreen();
    }

    @Override
    public void onFullScreenChanged(boolean fullScreen) {
        setViewVisibility();
    }

    @Override
    public void onViewActivated() {
        if (!mCallback.isFragmentActive(this)) {
            // we're not in the foreground; reset our view
            resetViews();
        } else {
            if (!isPhotoBound()) {
                // Restart the loader
                getLoaderManager().restartLoader(LOADER_ID_THUMBNAIL, null, this);
            }
            mCallback.onFragmentVisible(this);
        }
    }

    /**
     * Reset the views to their default states
     */
    public void resetViews() {
        if (mPhotoView != null) {
            mPhotoView.resetTransformations();
        }
    }

    @Override
    public boolean onInterceptMoveLeft(float origX, float origY) {
        if (!mCallback.isFragmentActive(this)) {
            // we're not in the foreground; don't intercept any touches
            return false;
        }

        return (mPhotoView != null && mPhotoView.interceptMoveLeft(origX, origY));
    }

    @Override
    public boolean onInterceptMoveRight(float origX, float origY) {
        if (!mCallback.isFragmentActive(this)) {
            // we're not in the foreground; don't intercept any touches
            return false;
        }

        return (mPhotoView != null && mPhotoView.interceptMoveRight(origX, origY));
    }

    /**
     * Returns {@code true} if a photo has been bound. Otherwise, returns {@code false}.
     */
    public boolean isPhotoBound() {
        return (mPhotoView != null && mPhotoView.isPhotoBound());
    }

    /**
     * Sets view visibility depending upon whether or not we're in "full screen" mode.
     */
    private void setViewVisibility() {
        final boolean fullScreen = mCallback == null ? false : mCallback.isFragmentFullScreen(this);
        setFullScreen(fullScreen);
    }

    /**
     * Sets full-screen mode for the views.
     */
    public void setFullScreen(boolean fullScreen) {
        mFullScreen = fullScreen;
    }

    @Override
    public void onCursorChanged(Cursor cursor) {
        if (mAdapter == null) {
            // The adapter is set in onAttach(), and is guaranteed to be non-null. We have magically
            // received an onCursorChanged without attaching to an activity. Ignore this cursor
            // change.
            return;
        }
        if (cursor.moveToPosition(mPosition) && !isPhotoBound()) {
            mCallback.onCursorChanged(this, cursor);

            final LoaderManager manager = getLoaderManager();
            final Loader<Bitmap> fakePhotoLoader = manager.getLoader(LOADER_ID_PHOTO);
            if (fakePhotoLoader != null) {
                final PhotoBitmapLoader loader = (PhotoBitmapLoader) fakePhotoLoader;
                mResolvedPhotoUri = mAdapter.getPhotoUri(cursor);
                loader.setPhotoUri(mResolvedPhotoUri);
                loader.forceLoad();
            }

            if (!mThumbnailShown) {
                final Loader<Bitmap> fakeThumbnailLoader = manager.getLoader(LOADER_ID_THUMBNAIL);
                if (fakeThumbnailLoader != null) {
                    final PhotoBitmapLoader loader = (PhotoBitmapLoader) fakeThumbnailLoader;
                    mThumbnailUri = mAdapter.getThumbnailUri(cursor);
                    loader.setPhotoUri(mThumbnailUri);
                    loader.forceLoad();
                }
            }
        }
    }

    public ProgressBarWrapper getPhotoProgressBar() {
        return mPhotoProgressBar;
    }

    public TextView getEmptyText() {
        return mEmptyText;
    }

    public ImageView getRetryButton() {
        return mRetryButton;
    }

    public boolean isProgressBarNeeded() {
        return mProgressBarNeeded;
    }
}
