/*
 * Copyright (C) 2012 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.mail.ui;

import android.app.Fragment;
import android.app.FragmentTransaction;
import android.appwidget.AppWidgetManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.DataSetObservable;
import android.database.DataSetObserver;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;

import com.android.bitmap.BitmapCache;
import com.android.mail.R;
import com.android.mail.bitmap.ContactResolver;
import com.android.mail.providers.Account;
import com.android.mail.providers.Folder;
import com.android.mail.providers.FolderWatcher;
import com.android.mail.utils.LogTag;
import com.android.mail.utils.LogUtils;
import com.android.mail.utils.MailObservable;
import com.android.mail.utils.Utils;
import com.android.mail.utils.VeiledAddressMatcher;
import com.android.mail.widget.WidgetProvider;

import java.util.ArrayList;

/**
 * This activity displays the list of available folders for the current account.
 */
public class FolderSelectionActivity extends ActionBarActivity implements OnClickListener,
        DialogInterface.OnClickListener, ControllableActivity,
        FolderSelector {
    public static final String EXTRA_ACCOUNT_SHORTCUT = "account-shortcut";

    private static final String LOG_TAG = LogTag.getLogTag();

    private static final int CONFIGURE = 0;

    private static final int VIEW = 1;

    private Account mAccount;
    private Folder mSelectedFolder;
    private boolean mConfigureShortcut;
    protected boolean mConfigureWidget;
    private int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
    private int mMode = -1;
    /** Empty placeholder for communicating to the consumer of the drawer observer. */
    private final DataSetObservable mFolderOrAccountObservers =
            new MailObservable("FolderOrAccount");

    private final AccountController mAccountController = new AccountController() {
        @Override
        public void registerAccountObserver(DataSetObserver observer) {
            // Do nothing
        }

        @Override
        public void unregisterAccountObserver(DataSetObserver observer) {
            // Do nothing
        }

        @Override
        public Account getAccount() {
            return mAccount;
        }

        @Override
        public void registerAllAccountObserver(DataSetObserver observer) {
            // Do nothing
        }

        @Override
        public void unregisterAllAccountObserver(DataSetObserver observer) {
            // Do nothing
        }

        @Override
        public Account[] getAllAccounts() {
            return new Account[]{mAccount};
        }

        @Override
        public VeiledAddressMatcher getVeiledAddressMatcher() {
            return null;
        }

        @Override
        public void switchToDefaultInboxOrChangeAccount(Account account) {
            // Never gets called, so do nothing here.
            LogUtils.wtf(LOG_TAG,"FolderSelectionActivity.switchToDefaultInboxOrChangeAccount() " +
                    "called when NOT expected.");
        }

        @Override
        public void registerFolderOrAccountChangedObserver(final DataSetObserver observer) {
            mFolderOrAccountObservers.registerObserver(observer);
        }

        @Override
        public void unregisterFolderOrAccountChangedObserver(final DataSetObserver observer) {
            mFolderOrAccountObservers.unregisterObserver(observer);
        }

        /**
         * Since there is no drawer to wait for, notifyChanged to the observers.
         */
        @Override
        public void closeDrawer(final boolean hasNewFolderOrAccount,
                Account account, Folder folder) {
            mFolderOrAccountObservers.notifyChanged();
        }

        @Override
        public void setFolderWatcher(FolderWatcher watcher) {
            // Unsupported.
        }

        @Override
        public boolean isDrawerPullEnabled() {
            // Unsupported
            return false;
        }

        @Override
        public int getFolderListViewChoiceMode() {
            return ListView.CHOICE_MODE_NONE;
        }
    };

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

        setContentView(R.layout.folders_activity);

        final Intent intent = getIntent();
        final String action = intent.getAction();
        mConfigureShortcut = Intent.ACTION_CREATE_SHORTCUT.equals(action);
        mConfigureWidget = AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action);
        if (!mConfigureShortcut && !mConfigureWidget) {
            LogUtils.wtf(LOG_TAG, "unexpected intent: %s", intent);
        }
        if (mConfigureShortcut || mConfigureWidget) {
            mMode = CONFIGURE;
        } else {
            mMode = VIEW;
        }

        if (mConfigureWidget) {
            mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                    AppWidgetManager.INVALID_APPWIDGET_ID);
            if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
                LogUtils.wtf(LOG_TAG, "invalid widgetId");
            }
        }

        mAccount = intent.getParcelableExtra(EXTRA_ACCOUNT_SHORTCUT);
        final Button firstButton = (Button) findViewById(R.id.first_button);
        firstButton.setVisibility(View.VISIBLE);
        // TODO(mindyp) disable the manage folders buttons until we have a manage folders screen.
        if (mMode == VIEW) {
            firstButton.setEnabled(false);
        }
        firstButton.setOnClickListener(this);
        createFolderListFragment(FolderListFragment.ofTopLevelTree(mAccount.folderListUri,
                getExcludedFolderTypes()));
    }

    /**
     * Create a Fragment showing this folder and its children.
     */
    private void createFolderListFragment(Fragment fragment) {
        final FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.content_pane, fragment);
        fragmentTransaction.commitAllowingStateLoss();
    }

    /**
     * Gets an {@link ArrayList} of canonical names of any folders to exclude from displaying.
     * By default, this list is empty.
     *
     * @return An {@link ArrayList} of folder canonical names
     */
    protected ArrayList<Integer> getExcludedFolderTypes() {
        return new ArrayList<Integer>();
    }

    @Override
    protected void onResume() {
        super.onResume();

        // TODO: (mindyp) Make sure we're operating on the same account as
        // before. If the user switched accounts, switch back.
    }

    @Override
    public void onClick(View v) {
        final int id = v.getId();
        if (id == R.id.first_button) {
            if (mMode == CONFIGURE) {
                doCancel();
            } else {
                // TODO (mindyp): open manage folders screen.
            }
        }
    }

    private void doCancel() {
        setResult(RESULT_CANCELED);
        finish();
    }

    /**
     * Create a widget for the specified account and folder
     */
    protected void createWidget(int id, Account account, Folder selectedFolder) {
        WidgetProvider.updateWidget(this, id, account, selectedFolder.type,
                selectedFolder.capabilities, selectedFolder.folderUri.fullUri,
                selectedFolder.conversationListUri, selectedFolder.name);
        final Intent result = new Intent();
        result.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id);
        setResult(RESULT_OK, result);
        finish();
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        if (which == DialogInterface.BUTTON_POSITIVE) {
            // The only dialog that is
            createWidget(mAppWidgetId, mAccount, mSelectedFolder);
        } else {
            doCancel();
        }
    }

    private void onFolderChanged(Folder folder, final boolean force) {
        if (!folder.equals(mSelectedFolder)) {
            mSelectedFolder = folder;
            Intent resultIntent = new Intent();

            if (mConfigureShortcut) {
                /*
                 * Create the shortcut Intent based on it with the additional
                 * information that we have in this activity: name of the
                 * account, calculate the human readable name of the folder and
                 * use it as the shortcut name, etc...
                 */
                final Intent clickIntent = Utils.createViewFolderIntent(this,
                        mSelectedFolder.folderUri.fullUri, mAccount);
                resultIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, clickIntent);
                resultIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
                        Intent.ShortcutIconResource.fromContext(this,
                                R.mipmap.ic_launcher_shortcut_folder));
                /**
                 * Note: Email1 created shortcuts using R.mipmap#ic_launcher_email
                 * so don't delete that resource until we have an upgrade/migration solution
                 */

                final CharSequence humanFolderName = mSelectedFolder.name;

                resultIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, humanFolderName);

                // Now ask the user what name they want for this shortcut. Pass
                // the
                // shortcut intent that we just created, the user can modify the
                // folder in
                // ShortcutNameActivity.
                final Intent shortcutNameIntent = new Intent(this, ShortcutNameActivity.class);
                shortcutNameIntent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY
                        | Intent.FLAG_ACTIVITY_FORWARD_RESULT);
                shortcutNameIntent.putExtra(ShortcutNameActivity.EXTRA_FOLDER_CLICK_INTENT,
                        resultIntent);
                shortcutNameIntent.putExtra(ShortcutNameActivity.EXTRA_SHORTCUT_NAME,
                        humanFolderName);

                startActivity(shortcutNameIntent);
                finish();
            } else if (mConfigureWidget) {
                createWidget(mAppWidgetId, mAccount, mSelectedFolder);
            }
        }
    }

    @Override
    public Context getActivityContext() {
        return this;
    }

    @Override
    public ViewMode getViewMode() {
        return null;
    }

    @Override
    public ConversationListCallbacks getListHandler() {
        return null;
    }

    @Override
    public ConversationCheckedSet getCheckedSet() {
        return null;
    }

    private Folder mNavigatedFolder;
    @Override
    public void onFolderSelected(Folder folder) {
        if (folder.hasChildren && !folder.equals(mNavigatedFolder)) {
            mNavigatedFolder = folder;
            // Replace this fragment with a new FolderListFragment
            // showing this folder's children if we are not already looking
            // at the child view for this folder.
            createFolderListFragment(FolderListFragment.ofTree(folder));
            return;
        }
        onFolderChanged(folder, false /* force */);
    }

    @Override
    public FolderSelector getFolderSelector() {
        return this;
    }

    @Override
    public void onUndoAvailable(ToastBarOperation undoOp) {
        // Do nothing.
    }

    @Override
    public Folder getHierarchyFolder() {
        return null;
    }

    @Override
    public ConversationUpdater getConversationUpdater() {
        return null;
    }

    @Override
    public ErrorListener getErrorListener() {
        return null;
    }

    @Override
    public void setPendingToastOperation(ToastBarOperation op) {
        // Do nothing.
    }

    @Override
    public ToastBarOperation getPendingToastOperation() {
        return null;
    }

    @Override
    public FolderController getFolderController() {
        return null;
    }

    @Override
    public void onAnimationEnd(AnimatedAdapter animatedAdapter) {
    }

    @Override
    public AccountController getAccountController() {
        return mAccountController;
    }

    @Override
    public void onFooterViewLoadMoreClick(Folder folder) {
        // Unsupported
    }

    @Override
    public RecentFolderController getRecentFolderController() {
        // Unsupported
        return null;
    }

    @Override
    public DrawerController getDrawerController() {
        // Unsupported
        return null;
    }

    @Override
    public KeyboardNavigationController getKeyboardNavigationController() {
        // Unsupported
        return null;
    }

    @Override
    public boolean isAccessibilityEnabled() {
        // Unsupported
        return true;
    }

    @Override
    public ConversationListHelper getConversationListHelper() {
        // Unsupported
        return null;
    }

    @Override
    public FragmentLauncher getFragmentLauncher() {
        // Unsupported
        return null;
    }

    @Override
    public ContactLoaderCallbacks getContactLoaderCallbacks() {
        // Unsupported
        return null;
    }

    @Override
    public ContactResolver getContactResolver(ContentResolver resolver, BitmapCache bitmapCache) {
        // Unsupported
        return null;
    }

    @Override
    public BitmapCache getSenderImageCache() {
        // Unsupported
        return null;
    }

    @Override
    public void resetSenderImageCache() {
        // Unsupported
    }

    @Override
    public void showHelp(Account account, int viewMode) {
        // Unsupported
    }
}
