/*
 * Copyright (C) 2015 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.contacts.editor;

import com.android.contacts.ContactSaveService;
import com.android.contacts.R;
import com.android.contacts.activities.CompactContactEditorActivity;
import com.android.contacts.common.model.AccountTypeManager;
import com.android.contacts.common.model.RawContactDelta;
import com.android.contacts.common.model.RawContactDeltaList;
import com.android.contacts.common.model.ValuesDelta;
import com.android.contacts.common.model.account.AccountType;
import com.android.contacts.common.util.ImplicitIntentsUtil;
import com.android.contacts.detail.PhotoSelectionHandler;
import com.android.contacts.util.ContactPhotoUtils;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;

import java.io.FileNotFoundException;

/**
 * Contact editor with only the most important fields displayed initially.
 */
public class CompactContactEditorFragment extends ContactEditorBaseFragment implements
        CompactRawContactsEditorView.Listener, PhotoSourceDialogFragment.Listener {

    private static final String KEY_PHOTO_URI = "photo_uri";
    private static final String KEY_PHOTO_RAW_CONTACT_ID = "photo_raw_contact_id";

    /**
     * Displays a PopupWindow with photo edit options.
     */
    final class PhotoHandler extends PhotoSelectionHandler implements View.OnClickListener {

        /**
         * Receiver of photo edit option callbacks.
         */
        private final class PhotoListener extends PhotoActionListener {

            @Override
            public void onRemovePictureChosen() {
                getContent().setPhoto(/* bitmap =*/ null);
                mUpdatedPhotos.remove(String.valueOf(mPhotoRawContactId));

                // Update the mode so the options change if user clicks the photo again
                mPhotoMode = getPhotoMode();
            }

            @Override
            public void onPhotoSelected(Uri uri) throws FileNotFoundException {
                final Bitmap bitmap = ContactPhotoUtils.getBitmapFromUri(getActivity(), uri);
                if (bitmap == null || bitmap.getHeight() <= 0 || bitmap.getWidth() <= 0) {
                    Log.w(TAG, "Invalid photo selected");
                }
                getContent().setPhoto(bitmap);

                // Clear any previously saved full resolution photos under negative raw contact IDs
                // so that we will use the newly selected photo, instead of an old one on rotations.
                removeNewRawContactPhotos();

                // If a new photo was chosen but not yet saved,
                // we need to update the UI immediately
                mUpdatedPhotos.putParcelable(String.valueOf(mPhotoRawContactId), uri);
                getContent().setFullSizePhoto(uri);

                // Update the mode so the options change if user clicks the photo again
                mPhotoMode = getPhotoMode();

                // Re-create the photo handler so that any additional photo selections create a
                // new temp file (and don't hit the one that was just added to the cache).
                mPhotoHandler = createPhotoHandler();
            }

            @Override
            public Uri getCurrentPhotoUri() {
                return mPhotoUri;
            }

            @Override
            public void onPhotoSelectionDismissed() {
            }
        }

        private PhotoListener mPhotoListener;
        private int mPhotoMode;

        public PhotoHandler(Context context, int photoMode, RawContactDeltaList state) {
            // We pass a null changeAnchorView since we are overriding onClick so that we
            // can show the photo options in a dialog instead of a ListPopupWindow (which would
            // be anchored at changeAnchorView).
            super(context, /* changeAnchorView =*/ null, photoMode, /* isDirectoryContact =*/ false,
                    state);
            mPhotoListener = new PhotoListener();
            mPhotoMode = photoMode;
        }

        @Override
        public void onClick(View view) {
            PhotoSourceDialogFragment.show(CompactContactEditorFragment.this, mPhotoMode);
        }

        @Override
        public PhotoActionListener getListener() {
            return mPhotoListener;
        }

        @Override
        protected void startPhotoActivity(Intent intent, int requestCode, Uri photoUri) {
            mPhotoUri = photoUri;
            mStatus = Status.SUB_ACTIVITY;

            CompactContactEditorFragment.this.startActivityForResult(intent, requestCode);
        }
    }

    private PhotoHandler mPhotoHandler;
    private Uri mPhotoUri;
    private long mPhotoRawContactId;

    @Override
    public void onCreate(Bundle savedState) {
        super.onCreate(savedState);

        if (savedState != null) {
            mPhotoUri = savedState.getParcelable(KEY_PHOTO_URI);
            mPhotoRawContactId = savedState.getLong(KEY_PHOTO_RAW_CONTACT_ID);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
        setHasOptionsMenu(true);

        final View view = inflater.inflate(
                R.layout.compact_contact_editor_fragment, container, false);
        mContent = (LinearLayout) view.findViewById(R.id.editors);
        return view;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        outState.putParcelable(KEY_PHOTO_URI, mPhotoUri);
        outState.putLong(KEY_PHOTO_RAW_CONTACT_ID, mPhotoRawContactId);
        super.onSaveInstanceState(outState);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (mStatus == Status.SUB_ACTIVITY) {
            mStatus = Status.EDITING;
        }
        if (mPhotoHandler != null
                && mPhotoHandler.handlePhotoActivityResult(requestCode, resultCode, data)) {
            return;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onStop() {
        super.onStop();

        // If anything was left unsaved, save it now
        if (!getActivity().isChangingConfigurations() && mStatus == Status.EDITING) {
            save(SaveMode.RELOAD);
        }
    }

    @Override
    protected void bindEditors() {
        if (!isReadyToBindEditors()) {
            return;
        }

        // Add input fields for the loaded Contact
        final CompactRawContactsEditorView editorView = getContent();
        editorView.setListener(this);
        editorView.setState(mState, getMaterialPalette(), mViewIdGenerator);

        // Set up the photo widget
        mPhotoHandler = createPhotoHandler();
        mPhotoRawContactId = editorView.getPhotoRawContactId();
        if (mPhotoRawContactId < 0) {
            // Since the raw contact IDs for new contacts are random negative numbers
            // we consider any negative key a match
            for (String key : mUpdatedPhotos.keySet()) {
                try {
                    if (Integer.parseInt(key) < 0) {
                        editorView.setFullSizePhoto((Uri) mUpdatedPhotos.getParcelable(key));
                        break;
                    }
                } catch (NumberFormatException ignored) {
                }
            }
        } else if (mUpdatedPhotos.containsKey(String.valueOf(mPhotoRawContactId))) {
            editorView.setFullSizePhoto((Uri) mUpdatedPhotos.getParcelable(
                    String.valueOf(mPhotoRawContactId)));
        }
        editorView.setPhotoHandler(mPhotoHandler);

        // The editor is ready now so make it visible
        editorView.setEnabled(isEnabled());
        editorView.setVisibility(View.VISIBLE);

        // Refresh the ActionBar as the visibility of the join command
        // Activity can be null if we have been detached from the Activity.
        invalidateOptionsMenu();
    }

    private boolean isReadyToBindEditors() {
        if (mState.isEmpty()) {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "No data to bind editors");
            }
            return false;
        }
        if (mIsEdit && !mExistingContactDataReady) {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "Existing contact data is not ready to bind editors.");
            }
            return false;
        }
        if (mHasNewContact && !mNewContactDataReady) {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "New contact data is not ready to bind editors.");
            }
            return false;
        }
        return true;
    }

    private PhotoHandler createPhotoHandler() {
        return new PhotoHandler(getActivity(), getPhotoMode(), mState);
    }

    private int getPhotoMode() {
        // To determine the options that are available to the user to update their photo
        // (i.e. the photo mode), check if any of the writable raw contacts has a photo set
        Integer photoMode = null;
        boolean hasWritableAccountType = false;
        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
        for (RawContactDelta rawContactDelta : mState) {
            if (!rawContactDelta.isVisible()) {
                continue;
            }
            final AccountType accountType = rawContactDelta.getAccountType(accountTypes);
            if (accountType.areContactsWritable()) {
                hasWritableAccountType = true;
                if (getContent().isWritablePhotoSet()) {
                    photoMode = PhotoActionPopup.Modes.MULTIPLE_WRITE_ABLE_PHOTOS;
                    break;
                }
            }
        }
        // If the mode was not set, base it on whether we saw a writable contact or not
        if (photoMode == null) {
            photoMode = hasWritableAccountType
                    ? PhotoActionPopup.Modes.NO_PHOTO : PhotoActionPopup.Modes.READ_ONLY_PHOTO;
        }
        return photoMode;
    }

    @Override
    protected View getAggregationAnchorView(long rawContactId) {
        return getContent().getAggregationAnchorView();
    }

    @Override
    protected void setGroupMetaData() {
        // The compact editor does not support groups.
    }

    @Override
    protected boolean doSaveAction(int saveMode) {
        // Save contact. No need to pass the palette since we are finished editing after the save.
        final Intent intent = ContactSaveService.createSaveContactIntent(mContext, mState,
                SAVE_MODE_EXTRA_KEY, saveMode, isEditingUserProfile(),
                ((Activity) mContext).getClass(),
                CompactContactEditorActivity.ACTION_SAVE_COMPLETED, mUpdatedPhotos);
        mContext.startService(intent);

        return true;
    }

    @Override
    protected void joinAggregate(final long contactId) {
        final Intent intent = ContactSaveService.createJoinContactsIntent(
                mContext, mContactIdForJoin, contactId, CompactContactEditorActivity.class,
                CompactContactEditorActivity.ACTION_JOIN_COMPLETED);
        mContext.startService(intent);
    }

    @Override
    public void onRemovePictureChosen() {
        if (mPhotoHandler != null) {
            mPhotoHandler.getListener().onRemovePictureChosen();
        }
    }

    @Override
    public void onTakePhotoChosen() {
        if (mPhotoHandler != null) {
            mPhotoHandler.getListener().onTakePhotoChosen();
        }
    }

    @Override
    public void onPickFromGalleryChosen() {
        if (mPhotoHandler != null) {
            mPhotoHandler.getListener().onPickFromGalleryChosen();
        }
    }

    @Override
    public void onExpandEditor() {
        // Determine if this is an insert (new contact) or edit
        final boolean isInsert = isInsert(getActivity().getIntent());

        if (isInsert) {
            // For inserts, prevent any changes from being saved when the base fragment is destroyed
            mStatus = Status.CLOSING;
        } else {
            // Prevent a Toast from being displayed as we transition to the full editor
            mShowToastAfterSave = false;

            // Save whatever is in the form
            save(SaveMode.RELOAD);
        }

        // Prepare an Intent to start the expanded editor
        final Intent intent = isInsert
                ? EditorIntents.createInsertContactIntent(mState, getDisplayName(), mUpdatedPhotos)
                : EditorIntents.createEditContactIntent(mLookupUri, getMaterialPalette());
        ImplicitIntentsUtil.startActivityInApp(getActivity(), intent);

        getActivity().finish();
    }

    @Override
    public void onNameFieldChanged(long rawContactId, ValuesDelta valuesDelta) {
        final Activity activity = getActivity();
        if (activity == null || activity.isFinishing()) {
            return;
        }
        if (!mIsUserProfile) {
            acquireAggregationSuggestions(activity, rawContactId, valuesDelta);
        }
    }

    @Override
    public String getDisplayName() {
        final StructuredNameEditorView structuredNameEditorView =
                getContent().getStructuredNameEditorView();
        return structuredNameEditorView == null
                ? null : structuredNameEditorView.getDisplayName();
    }

    private CompactRawContactsEditorView getContent() {
        return (CompactRawContactsEditorView) mContent;
    }
}
