MigrationEXP-master/AndroidAnalyzer/examples/VectorRoomSettingsFragment.java
/*
 * Copyright 2016 OpenMarket Ltd
 * Copyright 2017 Vector Creations Ltd
 * 
 * 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 im.vector.fragments;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.support.v4.content.ContextCompat;
import android.text.Html;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.PopupMenu;
import android.widget.Toast;

import org.matrix.androidsdk.MXSession;
import org.matrix.androidsdk.crypto.MXCryptoAlgorithms;
import org.matrix.androidsdk.data.Room;
import org.matrix.androidsdk.data.RoomAccountData;
import org.matrix.androidsdk.data.RoomState;
import org.matrix.androidsdk.data.RoomTag;
import org.matrix.androidsdk.listeners.IMXNetworkEventListener;
import org.matrix.androidsdk.listeners.MXEventListener;
import org.matrix.androidsdk.listeners.MXMediaUploadListener;
import org.matrix.androidsdk.rest.callback.ApiCallback;
import org.matrix.androidsdk.rest.callback.SimpleApiCallback;
import org.matrix.androidsdk.rest.model.Event;
import org.matrix.androidsdk.rest.model.MatrixError;
import org.matrix.androidsdk.rest.model.PowerLevels;
import org.matrix.androidsdk.rest.model.RoomMember;
import org.matrix.androidsdk.util.BingRulesManager;
import org.matrix.androidsdk.util.Log;
import org.matrix.androidsdk.util.ResourceUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import im.vector.Matrix;
import im.vector.R;;
import im.vector.VectorApp;
import im.vector.activity.CommonActivityUtils;
import im.vector.activity.VectorMediasPickerActivity;
import im.vector.activity.VectorMemberDetailsActivity;
import im.vector.preference.AddressPreference;
import im.vector.preference.RoomAvatarPreference;
import im.vector.preference.VectorCustomActionEditTextPreference;
import im.vector.preference.VectorListPreference;
import im.vector.preference.VectorSwitchPreference;
import im.vector.util.ThemeUtils;
import im.vector.util.VectorUtils;

import static android.preference.PreferenceManager.getDefaultSharedPreferences;

public class VectorRoomSettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
    // internal constants values
    private static final String LOG_TAG = VectorRoomSettingsFragment.class.getSimpleName();
    private static final boolean UPDATE_UI = true;
    private static final boolean DO_NOT_UPDATE_UI = false;
    private static final int REQ_CODE_UPDATE_ROOM_AVATAR = 0x10;

    // Room access rules values
    private static final String ACCESS_RULES_ONLY_PEOPLE_INVITED = "1";
    private static final String ACCESS_RULES_ANYONE_WITH_LINK_APART_GUEST = "2";
    private static final String ACCESS_RULES_ANYONE_WITH_LINK_INCLUDING_GUEST = "3";

    // fragment extra args keys
    private static final String EXTRA_MATRIX_ID = "KEY_EXTRA_MATRIX_ID";
    private static final String EXTRA_ROOM_ID = "KEY_EXTRA_ROOM_ID";

    // preference keys: public API to access preference
    private static final String PREF_KEY_ROOM_PHOTO_AVATAR = "roomPhotoAvatar";
    private static final String PREF_KEY_ROOM_NAME = "roomNameEditText";
    private static final String PREF_KEY_ROOM_TOPIC = "roomTopicEditText";
    private static final String PREF_KEY_ROOM_DIRECTORY_VISIBILITY_SWITCH = "roomNameListedInDirectorySwitch";
    private static final String PREF_KEY_ROOM_TAG_LIST = "roomTagList";
    private static final String PREF_KEY_ROOM_ACCESS_RULES_LIST = "roomAccessRulesList";
    private static final String PREF_KEY_ROOM_HISTORY_READABILITY_LIST = "roomReadHistoryRulesList";
    private static final String PREF_KEY_ROOM_NOTIFICATIONS_LIST = "roomNotificationPreference";
    private static final String PREF_KEY_ROOM_LEAVE = "roomLeave";
    private static final String PREF_KEY_ROOM_INTERNAL_ID = "roomInternalId";
    private static final String PREF_KEY_ADDRESSES = "addresses";
    private static final String PREF_KEY_ADVANCED = "advanced";

    private static final String PREF_KEY_BANNED = "banned";
    private static final String PREF_KEY_BANNED_DIVIDER = "banned_divider";
    private static final String PREF_KEY_ENCRYPTION = "encryptionKey";

    private static final String PREF_KEY_FLAIR = "flair";
    private static final String PREF_KEY_FLAIR_DIVIDER = "flair_divider";

    private static final String ADDRESSES_PREFERENCE_KEY_BASE = "ADDRESSES_PREFERENCE_KEY_BASE";
    private static final String NO_LOCAL_ADDRESS_PREFERENCE_KEY = "NO_LOCAL_ADDRESS_PREFERENCE_KEY";
    private static final String ADD_ADDRESSES_PREFERENCE_KEY = "ADD_ADDRESSES_PREFERENCE_KEY";

    private static final String BANNED_PREFERENCE_KEY_BASE = "BANNED_PREFERENCE_KEY_BASE";

    private static final String FLAIR_PREFERENCE_KEY_BASE = "FLAIR_PREFERENCE_KEY_BASE";

    private static final String UNKNOWN_VALUE = "UNKNOWN_VALUE";

    // business code
    private MXSession mSession;
    private Room mRoom;
    private BingRulesManager mBingRulesManager;
    private boolean mIsUiUpdateSkipped;

    // addresses
    private PreferenceCategory mAddressesSettingsCategory;

    // other
    private PreferenceCategory mAdvandceSettingsCategory;

    // banned members
    private PreferenceCategory mBannedMembersSettingsCategory;
    private PreferenceCategory mBannedMembersSettingsCategoryDivider;

    // flair
    private PreferenceCategory mFlairSettingsCategory;

    // UI elements
    private RoomAvatarPreference mRoomPhotoAvatar;
    private EditTextPreference mRoomNameEditTxt;
    private EditTextPreference mRoomTopicEditTxt;
    private CheckBoxPreference mRoomDirectoryVisibilitySwitch;
    private ListPreference mRoomTagListPreference;
    private VectorListPreference mRoomAccessRulesListPreference;
    private ListPreference mRoomHistoryReadabilityRulesListPreference;
    private View mParentLoadingView;
    private View mParentFragmentContainerView;
    private ListPreference mRoomNotificationsPreference;

    // disable some updates if there is
    private final IMXNetworkEventListener mNetworkListener = new IMXNetworkEventListener() {
        @Override
        public void onNetworkConnectionUpdate(boolean isConnected) {
            updateUi();
        }
    };

    // update field listener
    private final ApiCallback<Void> mUpdateCallback = new ApiCallback<Void>() {
        /**
         * refresh the fragment.
         * @param mode true to force refresh
         */
        private void onDone(final String message, final boolean mode) {
            if (null != getActivity()) {
                if (!TextUtils.isEmpty(message)) {
                    Toast.makeText(getActivity(), message, Toast.LENGTH_LONG).show();
                }

                // ensure that the response has been sent in the UI thread
                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        hideLoadingView(mode);
                    }
                });
            }
        }

        @Override
        public void onSuccess(Void info) {
            Log.d(LOG_TAG, "##update succeed");
            onDone(null, UPDATE_UI);
        }

        @Override
        public void onNetworkError(Exception e) {
            Log.w(LOG_TAG, "##NetworkError " + e.getLocalizedMessage());
            onDone(e.getLocalizedMessage(), DO_NOT_UPDATE_UI);
        }

        @Override
        public void onMatrixError(MatrixError e) {
            Log.w(LOG_TAG, "##MatrixError " + e.getLocalizedMessage());
            onDone(e.getLocalizedMessage(), DO_NOT_UPDATE_UI);
        }

        @Override
        public void onUnexpectedError(Exception e) {
            Log.w(LOG_TAG, "##UnexpectedError " + e.getLocalizedMessage());
            onDone(e.getLocalizedMessage(), DO_NOT_UPDATE_UI);
        }
    };

    // MX system events listener
    private final MXEventListener mEventListener = new MXEventListener() {
        @Override
        public void onLiveEvent(final Event event, RoomState roomState) {
            getActivity().runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    String eventType = event.getType();

                    // The various events that could possibly change the fragment items
                    if (Event.EVENT_TYPE_STATE_ROOM_NAME.equals(eventType)
                            || Event.EVENT_TYPE_STATE_ROOM_ALIASES.equals(eventType)
                            || Event.EVENT_TYPE_STATE_ROOM_MEMBER.equals(eventType)
                            || Event.EVENT_TYPE_STATE_ROOM_AVATAR.equals(eventType)
                            || Event.EVENT_TYPE_STATE_ROOM_TOPIC.equals(eventType)
                            || Event.EVENT_TYPE_STATE_ROOM_POWER_LEVELS.equals(eventType)
                            || Event.EVENT_TYPE_STATE_HISTORY_VISIBILITY.equals(eventType)
                            || Event.EVENT_TYPE_STATE_ROOM_JOIN_RULES.equals(eventType)    // room access rules
                            || Event.EVENT_TYPE_STATE_ROOM_GUEST_ACCESS.equals(eventType)  // room access rules
                            ) {
                        Log.d(LOG_TAG, "## onLiveEvent() event = " + eventType);
                        updateUi();
                    }

                    if (Event.EVENT_TYPE_MESSAGE_ENCRYPTION.equals(eventType)) {
                        refreshEndToEnd();
                    }

                    // aliases
                    if (Event.EVENT_TYPE_STATE_CANONICAL_ALIAS.equals(eventType)
                            || Event.EVENT_TYPE_STATE_ROOM_ALIASES.equals(eventType)
                            || Event.EVENT_TYPE_STATE_ROOM_POWER_LEVELS.equals(eventType)
                            ) {
                        Log.d(LOG_TAG, "## onLiveEvent() refresh the addresses list");
                        refreshAddresses();
                    }

                    if (Event.EVENT_TYPE_STATE_ROOM_MEMBER.equals(eventType)) {
                        Log.d(LOG_TAG, "## onLiveEvent() refresh the banned members list");
                        refreshBannedMembersList();
                    }
                }
            });
        }

        @Override
        public void onRoomFlush(String roomId) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    updateUi();
                }
            });
        }

        @Override
        public void onRoomTagEvent(String roomId) {
            Log.d(LOG_TAG, "## onRoomTagEvent()");
            updateUi();
        }

        @Override
        public void onBingRulesUpdate() {
            updateUi();
        }
    };

    public static VectorRoomSettingsFragment newInstance(String aMatrixId, String aRoomId) {
        VectorRoomSettingsFragment theFragment = new VectorRoomSettingsFragment();
        Bundle args = new Bundle();
        args.putString(EXTRA_MATRIX_ID, aMatrixId);
        args.putString(EXTRA_ROOM_ID, aRoomId);
        theFragment.setArguments(args);

        return theFragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(LOG_TAG, "## onCreate() IN");

        // retrieve fragment extras
        String matrixId = getArguments().getString(EXTRA_MATRIX_ID);
        String roomId = getArguments().getString(EXTRA_ROOM_ID);

        if (TextUtils.isEmpty(matrixId) || TextUtils.isEmpty(roomId)) {
            Log.e(LOG_TAG, "## onCreate(): fragment extras (MatrixId or RoomId) are missing");
            getActivity().finish();
        } else {
            mSession = Matrix.getInstance(getActivity()).getSession(matrixId);
            if ((null != mSession) && mSession.isAlive()) {
                mRoom = mSession.getDataHandler().getRoom(roomId);
                mBingRulesManager = mSession.getDataHandler().getBingRulesManager();
            }

            if (null == mRoom) {
                Log.e(LOG_TAG, "## onCreate(): unable to retrieve Room object");
                getActivity().finish();
            }
        }

        // load preference xml file
        addPreferencesFromResource(R.xml.vector_room_settings_preferences);

        // init preference fields
        mRoomPhotoAvatar = (RoomAvatarPreference) findPreference(PREF_KEY_ROOM_PHOTO_AVATAR);
        mRoomNameEditTxt = (EditTextPreference) findPreference(PREF_KEY_ROOM_NAME);
        mRoomTopicEditTxt = (EditTextPreference) findPreference(PREF_KEY_ROOM_TOPIC);
        mRoomDirectoryVisibilitySwitch = (CheckBoxPreference) findPreference(PREF_KEY_ROOM_DIRECTORY_VISIBILITY_SWITCH);
        mRoomTagListPreference = (ListPreference) findPreference(PREF_KEY_ROOM_TAG_LIST);
        mRoomAccessRulesListPreference = (VectorListPreference) findPreference(PREF_KEY_ROOM_ACCESS_RULES_LIST);
        mRoomHistoryReadabilityRulesListPreference = (ListPreference) findPreference(PREF_KEY_ROOM_HISTORY_READABILITY_LIST);
        mAddressesSettingsCategory = (PreferenceCategory) getPreferenceManager().findPreference(PREF_KEY_ADDRESSES);
        mAdvandceSettingsCategory = (PreferenceCategory) getPreferenceManager().findPreference(PREF_KEY_ADVANCED);
        mBannedMembersSettingsCategory = (PreferenceCategory) getPreferenceManager().findPreference(PREF_KEY_BANNED);
        mBannedMembersSettingsCategoryDivider = (PreferenceCategory) getPreferenceManager().findPreference(PREF_KEY_BANNED_DIVIDER);
        mFlairSettingsCategory = (PreferenceCategory) getPreferenceManager().findPreference(PREF_KEY_FLAIR);
        mRoomNotificationsPreference = (ListPreference) getPreferenceManager().findPreference(PREF_KEY_ROOM_NOTIFICATIONS_LIST);

        mRoomAccessRulesListPreference.setOnPreferenceWarningIconClickListener(new VectorListPreference.OnPreferenceWarningIconClickListener() {
            @Override
            public void onWarningIconClick(Preference preference) {
                displayAccessRoomWarning();
            }
        });

        // display the room Id.
        EditTextPreference roomInternalIdPreference = (EditTextPreference) findPreference(PREF_KEY_ROOM_INTERNAL_ID);
        if (null != roomInternalIdPreference) {
            roomInternalIdPreference.setSummary(mRoom.getRoomId());

            roomInternalIdPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                @Override
                public boolean onPreferenceClick(Preference preference) {
                    VectorUtils.copyToClipboard(getActivity(), mRoom.getRoomId());
                    return false;
                }
            });
        }

        // leave room
        EditTextPreference leaveRoomPreference = (EditTextPreference) findPreference(PREF_KEY_ROOM_LEAVE);

        if (null != leaveRoomPreference) {
            leaveRoomPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                @Override
                public boolean onPreferenceClick(Preference preference) {
                    // leave room
                    new AlertDialog.Builder(getActivity())
                            .setTitle(R.string.room_participants_leave_prompt_title)
                            .setMessage(getString(R.string.room_participants_leave_prompt_msg))
                            .setPositiveButton(R.string.leave, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    dialog.dismiss();
                                    displayLoadingView();

                                    mRoom.leave(new ApiCallback<Void>() {
                                        @Override
                                        public void onSuccess(Void info) {
                                            if (null != getActivity()) {
                                                getActivity().runOnUiThread(new Runnable() {
                                                    @Override
                                                    public void run() {
                                                        getActivity().finish();
                                                    }
                                                });
                                            }
                                        }

                                        private void onError(final String errorMessage) {
                                            if (null != getActivity()) {
                                                getActivity().runOnUiThread(new Runnable() {
                                                    @Override
                                                    public void run() {
                                                        hideLoadingView(true);
                                                        Toast.makeText(getActivity(), errorMessage, Toast.LENGTH_SHORT).show();
                                                    }
                                                });
                                            }
                                        }

                                        @Override
                                        public void onNetworkError(Exception e) {
                                            onError(e.getLocalizedMessage());
                                        }

                                        @Override
                                        public void onMatrixError(MatrixError e) {
                                            onError(e.getLocalizedMessage());
                                        }

                                        @Override
                                        public void onUnexpectedError(Exception e) {
                                            onError(e.getLocalizedMessage());
                                        }
                                    });

                                }
                            })
                            .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    dialog.dismiss();
                                }
                            })
                            .create()
                            .show();
                    return true;
                }
            });
        }

        // init the room avatar: session and room
        mRoomPhotoAvatar.setConfiguration(mSession, mRoom);
        mRoomPhotoAvatar.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference preference) {
                if ((null != mRoomPhotoAvatar) && mRoomPhotoAvatar.isEnabled()) {
                    onRoomAvatarPreferenceChanged();
                    return true; //True if the click was handled.
                } else
                    return false;
            }
        });

        // listen to preference changes
        enableSharedPreferenceListener(true);

        setRetainInstance(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = super.onCreateView(inflater, container, savedInstanceState);
        View listView = view.findViewById(android.R.id.list);

        if (null != listView) {
            listView.setPadding(0, 0, 0, 0);
        }

        // seems known issue that the preferences screen does not use the activity theme
        view.setBackgroundColor(ThemeUtils.getColor(getActivity(), R.attr.riot_primary_background_color));
        return view;
    }

    /**
     * This method expects a view with the id "settings_loading_layout",
     * that is present in the parent activity layout.
     *
     * @param view               fragment view
     * @param savedInstanceState bundle instance state
     */
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        // retrieve the loading screen in the parent view
        View parent = getView();
        if (null == mParentLoadingView) {
            while ((null != parent) && (null == mParentLoadingView)) {
                mParentLoadingView = parent.findViewById(R.id.settings_loading_layout);
                parent = (View) parent.getParent();
            }
        }

        // retrieve the parent fragment container view to disable access to the settings
        // while the loading screen is enabled
        parent = getView();
        if (null == mParentFragmentContainerView) {
            while ((null != parent) && (null == mParentFragmentContainerView)) {
                mParentFragmentContainerView = parent.findViewById(R.id.room_details_fragment_container);
                parent = (View) parent.getParent();
            }
        }
    }

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

        if (null != mRoom) {
            Matrix.getInstance(getActivity()).removeNetworkEventListener(mNetworkListener);
            mRoom.removeEventListener(mEventListener);
        }

        // remove preference changes listener
        enableSharedPreferenceListener(false);
    }

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

        if (null != mRoom) {
            Matrix.getInstance(getActivity()).addNetworkEventListener(mNetworkListener);
            mRoom.addEventListener(mEventListener);
            updateUi();

            updateRoomDirectoryVisibilityAsync();

            refreshAddresses();
            refreshFlair();
            refreshBannedMembersList();
            refreshEndToEnd();
        }
    }

    /**
     * Enable the preference listener according to the aIsListenerEnabled value.
     *
     * @param aIsListenerEnabled true to enable the listener, false otherwise
     */
    private void enableSharedPreferenceListener(boolean aIsListenerEnabled) {
        Log.d(LOG_TAG, "## enableSharedPreferenceListener(): aIsListenerEnabled=" + aIsListenerEnabled);

        mIsUiUpdateSkipped = !aIsListenerEnabled;

        try {
            //SharedPreferences prefMgr = getActivity().getSharedPreferences("VectorSettingsFile", Context.MODE_PRIVATE);
            SharedPreferences prefMgr = getDefaultSharedPreferences(getActivity());

            if (aIsListenerEnabled) {
                prefMgr.registerOnSharedPreferenceChangeListener(this);
            } else {
                prefMgr.unregisterOnSharedPreferenceChangeListener(this);
            }
        } catch (Exception ex) {
            Log.e(LOG_TAG, "## enableSharedPreferenceListener(): Exception Msg=" + ex.getMessage());
        }
    }

    /**
     * Update the preferences according to the power levels and its values.
     * To prevent the preference change listener to be triggered, the listener
     * is removed when the preferences are updated.
     */
    private void updateUi() {
        // configure the preferences that are allowed to be modified by the user
        updatePreferenceAccessFromPowerLevel();

        // need to run on the UI thread to be taken into account
        // when updatePreferenceUiValues() will be performed
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                // disable listener during preferences update, otherwise it will
                // be seen as a user action..
                enableSharedPreferenceListener(false);
            }
        });

        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                // set settings UI values
                updatePreferenceUiValues();

                // re enable preferences listener..
                enableSharedPreferenceListener(true);
            }
        });
    }

    /**
     * delayed refresh the preferences items.
     */
    private void updateUiOnUiThread() {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                updateUi();
            }
        });
    }

    /**
     * Retrieve the room visibility directory value and update the corresponding preference.
     * This is an asynchronous request: the call-back response will be processed on the UI thread.
     * For now, the room visibility directory value is not provided in the sync API, a specific request
     * must performed.
     */
    private void updateRoomDirectoryVisibilityAsync() {
        if ((null == mRoom) || (null == mRoomDirectoryVisibilitySwitch)) {
            Log.w(LOG_TAG, "## updateRoomDirectoryVisibilityUi(): not processed due to invalid parameters");
        } else {
            displayLoadingView();

            // server request: is the room listed in the room directory?
            mRoom.getDirectoryVisibility(mRoom.getRoomId(), new ApiCallback<String>() {

                private void handleResponseOnUiThread(final String aVisibilityValue) {
                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            // only stop loading screen and do not update UI since the
                            // update is done here below..
                            hideLoadingView(DO_NOT_UPDATE_UI);

                            // set checked status
                            // Note: the preference listener is disabled when the switch is updated, otherwise it will be seen
                            // as a user action on the preference
                            boolean isChecked = RoomState.DIRECTORY_VISIBILITY_PUBLIC.equals(aVisibilityValue);
                            enableSharedPreferenceListener(false);
                            mRoomDirectoryVisibilitySwitch.setChecked(isChecked);
                            enableSharedPreferenceListener(true);
                        }
                    });
                }

                @Override
                public void onSuccess(String visibility) {
                    handleResponseOnUiThread(visibility);
                }

                @Override
                public void onNetworkError(Exception e) {
                    Log.w(LOG_TAG, "## getDirectoryVisibility(): onNetworkError Msg=" + e.getLocalizedMessage());
                    handleResponseOnUiThread(null);
                }

                @Override
                public void onMatrixError(MatrixError matrixError) {
                    Log.w(LOG_TAG, "## getDirectoryVisibility(): onMatrixError Msg=" + matrixError.getLocalizedMessage());
                    handleResponseOnUiThread(null);
                }

                @Override
                public void onUnexpectedError(Exception e) {
                    Log.w(LOG_TAG, "## getDirectoryVisibility(): onUnexpectedError Msg=" + e.getLocalizedMessage());
                    handleResponseOnUiThread(null);
                }
            });
        }
    }


    /**
     * Display the access room warning.
     */
    private void displayAccessRoomWarning() {
        Toast.makeText(getActivity(), R.string.room_settings_room_access_warning, Toast.LENGTH_SHORT).show();
    }

    /**
     * Enable / disable preferences according to the power levels.
     */
    private void updatePreferenceAccessFromPowerLevel() {
        boolean canUpdateAvatar = false;
        boolean canUpdateName = false;
        boolean canUpdateTopic = false;
        boolean isAdmin = false;
        boolean isConnected = Matrix.getInstance(getActivity()).isConnected();

        // cannot refresh if there is no valid session / room
        if ((null != mRoom) && (null != mSession)) {
            PowerLevels powerLevels = mRoom.getLiveState().getPowerLevels();

            if (null != powerLevels) {
                int powerLevel = powerLevels.getUserPowerLevel(mSession.getMyUserId());
                canUpdateAvatar = powerLevel >= powerLevels.minimumPowerLevelForSendingEventAsStateEvent(Event.EVENT_TYPE_STATE_ROOM_AVATAR);
                canUpdateName = powerLevel >= powerLevels.minimumPowerLevelForSendingEventAsStateEvent(Event.EVENT_TYPE_STATE_ROOM_NAME);
                canUpdateTopic = powerLevel >= powerLevels.minimumPowerLevelForSendingEventAsStateEvent(Event.EVENT_TYPE_STATE_ROOM_TOPIC);
                isAdmin = (powerLevel >= CommonActivityUtils.UTILS_POWER_LEVEL_ADMIN);
            }
        } else {
            Log.w(LOG_TAG, "## updatePreferenceAccessFromPowerLevel(): session or room may be missing");
        }

        if (null != mRoomPhotoAvatar)
            mRoomPhotoAvatar.setEnabled(canUpdateAvatar && isConnected);


        if (null != mRoomNameEditTxt)
            mRoomNameEditTxt.setEnabled(canUpdateName && isConnected);

        if (null != mRoomTopicEditTxt)
            mRoomTopicEditTxt.setEnabled(canUpdateTopic && isConnected);

        // room present in the directory list: admin only
        if (null != mRoomDirectoryVisibilitySwitch)
            mRoomDirectoryVisibilitySwitch.setEnabled(isAdmin && isConnected);

        // room tagging: no power condition
        if (null != mRoomTagListPreference)
            mRoomTagListPreference.setEnabled(isConnected);

        // room access rules: admin only
        if (null != mRoomAccessRulesListPreference) {
            mRoomAccessRulesListPreference.setEnabled(isAdmin && isConnected);
            mRoomAccessRulesListPreference.setWarningIconVisible((0 == mRoom.getAliases().size()) && !TextUtils.equals(RoomState.JOIN_RULE_INVITE, mRoom.getLiveState().join_rule));
        }

        // room read history: admin only
        if (null != mRoomHistoryReadabilityRulesListPreference) {
            mRoomHistoryReadabilityRulesListPreference.setEnabled(isAdmin && isConnected);
        }

        if (null != mRoomNotificationsPreference) {
            mRoomNotificationsPreference.setEnabled(isConnected);
        }
    }


    /**
     * Update the UI preference from the values taken from
     * the SDK layer.
     */
    private void updatePreferenceUiValues() {
        String value;
        String summary;
        Resources resources;

        if ((null == mSession) || (null == mRoom)) {
            Log.w(LOG_TAG, "## updatePreferenceUiValues(): session or room may be missing");
            return;
        }

        if (null != mRoomPhotoAvatar) {
            mRoomPhotoAvatar.refreshAvatar();
        }

        // update the room name preference
        if (null != mRoomNameEditTxt) {
            value = mRoom.getLiveState().name;
            mRoomNameEditTxt.setSummary(value);
            mRoomNameEditTxt.setText(value);
        }

        // update the room topic preference
        if (null != mRoomTopicEditTxt) {
            value = mRoom.getTopic();
            mRoomTopicEditTxt.setSummary(value);
            mRoomTopicEditTxt.setText(value);
        }

        // update room directory visibility
//        if(null != mRoomDirectoryVisibilitySwitch) {
//            boolean isRoomPublic = TextUtils.equals(mRoom.getVisibility()/*getLiveState().visibility ou .isPublic()*/, RoomState.DIRECTORY_VISIBILITY_PUBLIC);
//            if(isRoomPublic !isRoomPublic= mRoomDirectoryVisibilitySwitch.isChecked())
//                mRoomDirectoryVisibilitySwitch.setChecked(isRoomPublic);
//        }

        // check if fragment is added to its Activity before calling getResources().
        // getResources() may throw an exception ".. not attached to Activity"
        if (!isAdded()) {
            Log.e(LOG_TAG, "## updatePreferenceUiValues(): fragment not added to Activity - isAdded()=false");
            return;
        } else {
            // in some weird cases, even if isAdded() = true, sometimes getResources() may fail,
            // so we need to catch the exception
            try {
                resources = getResources();
            } catch (Exception ex) {
                Log.e(LOG_TAG, "## updatePreferenceUiValues(): Exception in getResources() - Msg=" + ex.getLocalizedMessage());
                return;
            }
        }

        // room guest access rules
        if ((null != mRoomAccessRulesListPreference) && (null != resources)) {
            String joinRule = mRoom.getLiveState().join_rule;
            String guestAccessRule = mRoom.getLiveState().getGuestAccess();

            if (RoomState.JOIN_RULE_INVITE.equals(joinRule)/* && RoomState.GUEST_ACCESS_CAN_JOIN.equals(guestAccessRule)*/) {
                // "Only people who have been invited" requires: {join_rule: "invite"} and {guest_access: "can_join"}
                value = ACCESS_RULES_ONLY_PEOPLE_INVITED;
                summary = resources.getString(R.string.room_settings_room_access_entry_only_invited);
            } else if (RoomState.JOIN_RULE_PUBLIC.equals(joinRule) && RoomState.GUEST_ACCESS_FORBIDDEN.equals(guestAccessRule)) {
                // "Anyone who knows the room's link, apart from guests" requires: {join_rule: "public"} and {guest_access: "forbidden"}
                value = ACCESS_RULES_ANYONE_WITH_LINK_APART_GUEST;
                summary = resources.getString(R.string.room_settings_room_access_entry_anyone_with_link_apart_guest);
            } else if (RoomState.JOIN_RULE_PUBLIC.equals(joinRule) && RoomState.GUEST_ACCESS_CAN_JOIN.equals(guestAccessRule)) {
                // "Anyone who knows the room's link, including guests" requires: {join_rule: "public"} and {guest_access: "can_join"}
                value = ACCESS_RULES_ANYONE_WITH_LINK_INCLUDING_GUEST;
                summary = resources.getString(R.string.room_settings_room_access_entry_anyone_with_link_including_guest);
            } else {
                // unknown combination value
                value = null;
                summary = null;
                Log.w(LOG_TAG, "## updatePreferenceUiValues(): unknown room access configuration joinRule=" + joinRule + " and guestAccessRule=" + guestAccessRule);
            }

            if (null != value) {
                mRoomAccessRulesListPreference.setValue(value);
                mRoomAccessRulesListPreference.setSummary(summary);
            } else {
                mRoomHistoryReadabilityRulesListPreference.setValue(UNKNOWN_VALUE);
                mRoomHistoryReadabilityRulesListPreference.setSummary("");
            }
        }

        if (null != mRoomNotificationsPreference) {
            BingRulesManager.RoomNotificationState state = mSession.getDataHandler().getBingRulesManager().getRoomNotificationState(mRoom.getRoomId());

            if (state == BingRulesManager.RoomNotificationState.ALL_MESSAGES_NOISY) {
                value = getString(R.string.room_settings_all_messages_noisy);
            } else if (state == BingRulesManager.RoomNotificationState.ALL_MESSAGES) {
                value = getString(R.string.room_settings_all_messages);
            } else if (state == BingRulesManager.RoomNotificationState.MENTIONS_ONLY) {
                value = getString(R.string.room_settings_mention_only);
            } else {
                value = getString(R.string.room_settings_mute);
            }

            mRoomNotificationsPreference.setValue(value);
            mRoomNotificationsPreference.setSummary(value);
        }

        // update the room tag preference
        if (null != mRoomTagListPreference) {

            if (null != mRoom.getAccountData() && (null != resources)) {
                //Set<String> customTagList = mRoom.getAccountData().getKeys();

                if (null != mRoom.getAccountData().roomTag(RoomTag.ROOM_TAG_FAVOURITE)) {
                    value = resources.getString(R.string.room_settings_tag_pref_entry_value_favourite);
                    summary = resources.getString(R.string.room_settings_tag_pref_entry_favourite);
                } else if (null != mRoom.getAccountData().roomTag(RoomTag.ROOM_TAG_LOW_PRIORITY)) {
                    value = resources.getString(R.string.room_settings_tag_pref_entry_value_low_priority);
                    summary = resources.getString(R.string.room_settings_tag_pref_entry_low_priority);
                /* For further use in case of multiple tags support
                } else if(!mRoom.getAccountData().getKeys().isEmpty()) {
                    for(String tag : customTagList){
                        summary += (!summary.isEmpty()?" ":"") + tag;
                    }*/
                } else {
                    // no tag associated to the room
                    value = resources.getString(R.string.room_settings_tag_pref_entry_value_none);
                    summary = Html.fromHtml("<i>" + getResources().getString(R.string.room_settings_tag_pref_no_tag) + "</i>").toString();
                }

                mRoomTagListPreference.setValue(value);
                mRoomTagListPreference.setSummary(summary);
            }
        }

        // room history readability
        if (null != mRoomHistoryReadabilityRulesListPreference) {
            value = mRoom.getLiveState().getHistoryVisibility();
            summary = null;

            if ((null != value) && (null != resources)) {
                // get summary value
                if (value.equals(resources.getString(R.string.room_settings_read_history_entry_value_anyone))) {
                    summary = resources.getString(R.string.room_settings_read_history_entry_anyone);
                } else if (value.equals(resources.getString(R.string.room_settings_read_history_entry_value_members_only_option_time_shared))) {
                    summary = resources.getString(R.string.room_settings_read_history_entry_members_only_option_time_shared);
                } else if (value.equals(resources.getString(R.string.room_settings_read_history_entry_value_members_only_invited))) {
                    summary = resources.getString(R.string.room_settings_read_history_entry_members_only_invited);
                } else if (value.equals(resources.getString(R.string.room_settings_read_history_entry_value_members_only_joined))) {
                    summary = resources.getString(R.string.room_settings_read_history_entry_members_only_joined);
                } else {
                    // unknown value
                    Log.w(LOG_TAG, "## updatePreferenceUiValues(): unknown room read history value=" + value);
                    summary = null;
                }
            }

            if (null != summary) {
                mRoomHistoryReadabilityRulesListPreference.setValue(value);
                mRoomHistoryReadabilityRulesListPreference.setSummary(summary);
            } else {
                mRoomHistoryReadabilityRulesListPreference.setValue(UNKNOWN_VALUE);
                mRoomHistoryReadabilityRulesListPreference.setSummary("");
            }
        }
    }

    // OnSharedPreferenceChangeListener implementation

    /**
     * Main entry point handler for any preference changes. For each setting a dedicated handler is
     * called to process the setting.
     *
     * @param aSharedPreferences preference instance
     * @param aKey               preference key as it is defined in the XML
     */
    @Override
    public void onSharedPreferenceChanged(SharedPreferences aSharedPreferences, String aKey) {

        if (mIsUiUpdateSkipped) {
            Log.d(LOG_TAG, "## onSharedPreferenceChanged(): Skipped");
            return;
        }

        if (null == getActivity()) {
            Log.d(LOG_TAG, "## onSharedPreferenceChanged(): no attached to an activity");
            return;
        }

        if (aKey.equals(PREF_KEY_ROOM_PHOTO_AVATAR)) {
            // unused flow: onSharedPreferenceChanged not triggered for room avatar photo
            onRoomAvatarPreferenceChanged();
        } else if (aKey.equals(PREF_KEY_ROOM_NAME)) {
            onRoomNamePreferenceChanged();
        } else if (aKey.equals(PREF_KEY_ROOM_TOPIC)) {
            onRoomTopicPreferenceChanged();
        } else if (aKey.equals(PREF_KEY_ROOM_NOTIFICATIONS_LIST)) {
            onRoomNotificationsPreferenceChanged();
        } else if (aKey.equals(PREF_KEY_ROOM_DIRECTORY_VISIBILITY_SWITCH)) {
            onRoomDirectoryVisibilityPreferenceChanged(); // TBT
        } else if (aKey.equals(PREF_KEY_ROOM_TAG_LIST)) {
            onRoomTagPreferenceChanged(); // TBT
        } else if (aKey.equals(PREF_KEY_ROOM_ACCESS_RULES_LIST)) {
            onRoomAccessPreferenceChanged();
        } else if (aKey.equals(PREF_KEY_ROOM_HISTORY_READABILITY_LIST)) {
            onRoomHistoryReadabilityPreferenceChanged(); // TBT
        } else {
            Log.w(LOG_TAG, "## onSharedPreferenceChanged(): unknown aKey = " + aKey);
        }
    }

    /**
     * The room history readability has been updated.
     */
    private void onRoomHistoryReadabilityPreferenceChanged() {
        // sanity check
        if ((null == mRoom) || (null == mRoomHistoryReadabilityRulesListPreference)) {
            Log.w(LOG_TAG, "## onRoomHistoryReadabilityPreferenceChanged(): not processed due to invalid parameters");
            return;
        }

        // get new and previous values
        String previousValue = mRoom.getLiveState().history_visibility;
        String newValue = mRoomHistoryReadabilityRulesListPreference.getValue();

        if (!TextUtils.equals(newValue, previousValue)) {
            String historyVisibility;

            if (newValue.equals(getResources().getString(R.string.room_settings_read_history_entry_value_anyone))) {
                historyVisibility = RoomState.HISTORY_VISIBILITY_WORLD_READABLE;
            } else if (newValue.equals(getResources().getString(R.string.room_settings_read_history_entry_value_members_only_option_time_shared))) {
                historyVisibility = RoomState.HISTORY_VISIBILITY_SHARED;
            } else if (newValue.equals(getResources().getString(R.string.room_settings_read_history_entry_value_members_only_invited))) {
                historyVisibility = RoomState.HISTORY_VISIBILITY_INVITED;
            } else if (newValue.equals(getResources().getString(R.string.room_settings_read_history_entry_value_members_only_joined))) {
                historyVisibility = RoomState.HISTORY_VISIBILITY_JOINED;
            } else {
                // unknown value
                Log.w(LOG_TAG, "## onRoomHistoryReadabilityPreferenceChanged(): unknown value:" + newValue);
                historyVisibility = null;
            }

            if (null != historyVisibility) {
                displayLoadingView();
                mRoom.updateHistoryVisibility(historyVisibility, mUpdateCallback);
            }
        }
    }

    private void onRoomTagPreferenceChanged() {
        boolean isSupportedTag = true;

        // sanity check
        if ((null == mRoom) || (null == mRoomTagListPreference)) {
            Log.w(LOG_TAG, "## onRoomTagPreferenceChanged(): not processed due to invalid parameters");
        } else {
            String newTag = mRoomTagListPreference.getValue();
            String currentTag = null;
            Double tagOrder = 0.0;

            // retrieve the tag from the room info
            RoomAccountData accountData = mRoom.getAccountData();
            if ((null != accountData) && accountData.hasTags()) {
                currentTag = accountData.getKeys().iterator().next();
            }

            if (!newTag.equals(currentTag)) {
                if (newTag.equals(getResources().getString(R.string.room_settings_tag_pref_entry_value_favourite))) {
                    newTag = RoomTag.ROOM_TAG_FAVOURITE;
                } else if (newTag.equals(getResources().getString(R.string.room_settings_tag_pref_entry_value_low_priority))) {
                    newTag = RoomTag.ROOM_TAG_LOW_PRIORITY;
                } else if (newTag.equals(getResources().getString(R.string.room_settings_tag_pref_entry_value_none))) {
                    newTag = null;
                } else {
                    // unknown tag.. very unlikely
                    isSupportedTag = false;
                    Log.w(LOG_TAG, "## onRoomTagPreferenceChanged() not supported tag = " + newTag);
                }
            }

            if (isSupportedTag) {
                displayLoadingView();
                mRoom.replaceTag(currentTag, newTag, tagOrder, mUpdateCallback);
            }
        }
    }

    private void onRoomAccessPreferenceChanged() {

        if ((null == mRoom) || (null == mRoomAccessRulesListPreference)) {
            Log.w(LOG_TAG, "## onRoomAccessPreferenceChanged(): not processed due to invalid parameters");
        } else {
            String joinRuleToApply = null;
            String guestAccessRuleToApply = null;

            // get new and previous values
            String previousJoinRule = mRoom.getLiveState().join_rule;
            String previousGuestAccessRule = mRoom.getLiveState().getGuestAccess();
            String newValue = mRoomAccessRulesListPreference.getValue();

            if (ACCESS_RULES_ONLY_PEOPLE_INVITED.equals(newValue)) {
                // requires: {join_rule: "invite"} and {guest_access: "can_join"}
                joinRuleToApply = !RoomState.JOIN_RULE_INVITE.equals(previousJoinRule) ? RoomState.JOIN_RULE_INVITE : null;
                guestAccessRuleToApply = !RoomState.GUEST_ACCESS_CAN_JOIN.equals(previousGuestAccessRule) ? RoomState.GUEST_ACCESS_CAN_JOIN : null;
            } else if (ACCESS_RULES_ANYONE_WITH_LINK_APART_GUEST.equals(newValue)) {
                // requires: {join_rule: "public"} and {guest_access: "forbidden"}
                joinRuleToApply = !RoomState.JOIN_RULE_PUBLIC.equals(previousJoinRule) ? RoomState.JOIN_RULE_PUBLIC : null;
                guestAccessRuleToApply = !RoomState.GUEST_ACCESS_FORBIDDEN.equals(previousGuestAccessRule) ? RoomState.GUEST_ACCESS_FORBIDDEN : null;

                if (0 == mRoom.getAliases().size()) {
                    displayAccessRoomWarning();
                }
            } else if (ACCESS_RULES_ANYONE_WITH_LINK_INCLUDING_GUEST.equals(newValue)) {
                // requires: {join_rule: "public"} and {guest_access: "can_join"}
                joinRuleToApply = !RoomState.JOIN_RULE_PUBLIC.equals(previousJoinRule) ? RoomState.JOIN_RULE_PUBLIC : null;
                guestAccessRuleToApply = !RoomState.GUEST_ACCESS_CAN_JOIN.equals(previousGuestAccessRule) ? RoomState.GUEST_ACCESS_CAN_JOIN : null;

                if (0 == mRoom.getAliases().size()) {
                    displayAccessRoomWarning();
                }
            } else {
                // unknown value
                Log.d(LOG_TAG, "## onRoomAccessPreferenceChanged(): unknown selected value = " + newValue);
            }

            if (null != joinRuleToApply) {
                displayLoadingView();
                mRoom.updateJoinRules(joinRuleToApply, mUpdateCallback);
            }

            if (null != guestAccessRuleToApply) {
                displayLoadingView();
                mRoom.updateGuestAccess(guestAccessRuleToApply, mUpdateCallback);
            }
        }
    }

    private void onRoomDirectoryVisibilityPreferenceChanged() {
        String visibility;

        if ((null == mRoom) || (null == mRoomDirectoryVisibilitySwitch)) {
            Log.w(LOG_TAG, "## onRoomDirectoryVisibilityPreferenceChanged(): not processed due to invalid parameters");
            visibility = null;
        } else if (mRoomDirectoryVisibilitySwitch.isChecked()) {
            visibility = RoomState.DIRECTORY_VISIBILITY_PUBLIC;
        } else {
            visibility = RoomState.DIRECTORY_VISIBILITY_PRIVATE;
        }

        if (null != visibility) {
            Log.d(LOG_TAG, "## onRoomDirectoryVisibilityPreferenceChanged(): directory visibility set to " + visibility);
            displayLoadingView();
            mRoom.updateDirectoryVisibility(visibility, mUpdateCallback);
        }
    }

    /**
     */
    private void onRoomNotificationsPreferenceChanged() {
        // sanity check
        if ((null == mRoom) || (null == mBingRulesManager)) {
            return;
        }

        String value = mRoomNotificationsPreference.getValue();
        BingRulesManager.RoomNotificationState updatedState;

        if (TextUtils.equals(value, getString(R.string.room_settings_all_messages_noisy))) {
            updatedState = BingRulesManager.RoomNotificationState.ALL_MESSAGES_NOISY;
        } else if (TextUtils.equals(value, getString(R.string.room_settings_all_messages))) {
            updatedState = BingRulesManager.RoomNotificationState.ALL_MESSAGES;
        } else if (TextUtils.equals(value, getString(R.string.room_settings_mention_only))) {
            updatedState = BingRulesManager.RoomNotificationState.MENTIONS_ONLY;
        } else {
            updatedState = BingRulesManager.RoomNotificationState.MUTE;
        }

        // update only, if values are different
        if (mBingRulesManager.getRoomNotificationState(mRoom.getRoomId()) != updatedState) {
            displayLoadingView();
            mBingRulesManager.updateRoomNotificationState(mRoom.getRoomId(), updatedState,
                    new BingRulesManager.onBingRuleUpdateListener() {
                        @Override
                        public void onBingRuleUpdateSuccess() {
                            Log.d(LOG_TAG, "##onRoomNotificationsPreferenceChanged(): update succeed");
                            hideLoadingView(UPDATE_UI);
                        }

                        @Override
                        public void onBingRuleUpdateFailure(String errorMessage) {
                            Log.w(LOG_TAG, "##onRoomNotificationsPreferenceChanged(): BingRuleUpdateFailure");
                            hideLoadingView(DO_NOT_UPDATE_UI);
                        }
                    });
        }
    }

    /**
     * Action when updating the room name.
     */
    private void onRoomNamePreferenceChanged() {
        // sanity check
        if ((null == mRoom) || (null == mSession) || (null == mRoomNameEditTxt)) {
            return;
        }

        // get new and previous values
        String previousName = mRoom.getLiveState().name;
        String newName = mRoomNameEditTxt.getText();
        // update only, if values are different
        if (!TextUtils.equals(previousName, newName)) {
            displayLoadingView();

            Log.d(LOG_TAG, "##onRoomNamePreferenceChanged to " + newName);
            mRoom.updateName(newName, mUpdateCallback);
        }
    }

    /**
     * Action when updating the room topic.
     */
    private void onRoomTopicPreferenceChanged() {
        // sanity check
        if (null == mRoom) {
            return;
        }

        // get new and previous values
        String previousTopic = mRoom.getTopic();
        String newTopic = mRoomTopicEditTxt.getText();
        // update only, if values are different
        if (!TextUtils.equals(previousTopic, newTopic)) {
            displayLoadingView();
            Log.d(LOG_TAG, "## update topic to " + newTopic);
            mRoom.updateTopic(newTopic, mUpdateCallback);
        }

    }

    /**
     * Update the room avatar.
     * Start the camera activity to take the avatar picture.
     */
    private void onRoomAvatarPreferenceChanged() {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Intent intent = new Intent(getActivity(), VectorMediasPickerActivity.class);
                intent.putExtra(VectorMediasPickerActivity.EXTRA_AVATAR_MODE, true);
                startActivityForResult(intent, REQ_CODE_UPDATE_ROOM_AVATAR);
            }
        });
    }

    /**
     * Process the result of the room avatar picture.
     *
     * @param aRequestCode request ID
     * @param aResultCode  request status code
     * @param aData        result data
     */
    @Override
    public void onActivityResult(int aRequestCode, int aResultCode, final Intent aData) {
        super.onActivityResult(aRequestCode, aResultCode, aData);

        if (REQ_CODE_UPDATE_ROOM_AVATAR == aRequestCode) {
            onActivityResultRoomAvatarUpdate(aResultCode, aData);
        }
    }

    /**
     * Update the avatar from the data provided the medias picker.
     *
     * @param aResultCode the result code.
     * @param aData       the provided data.
     */
    private void onActivityResultRoomAvatarUpdate(int aResultCode, final Intent aData) {
        // sanity check
        if (null == mSession) {
            return;
        }

        if (aResultCode == Activity.RESULT_OK) {
            Uri thumbnailUri = VectorUtils.getThumbnailUriFromIntent(getActivity(), aData, mSession.getMediasCache());

            if (null != thumbnailUri) {
                displayLoadingView();

                // save the bitmap URL on the server
                ResourceUtils.Resource resource = ResourceUtils.openResource(getActivity(), thumbnailUri, null);
                if (null != resource) {
                    mSession.getMediasCache().uploadContent(resource.mContentStream, null, resource.mMimeType, null, new MXMediaUploadListener() {

                        @Override
                        public void onUploadError(String uploadId, int serverResponseCode, String serverErrorMessage) {
                            getActivity().runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    Log.e(LOG_TAG, "Fail to upload the avatar");
                                    hideLoadingView(DO_NOT_UPDATE_UI);
                                }
                            });
                        }

                        @Override
                        public void onUploadComplete(final String uploadId, final String contentUri) {
                            getActivity().runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    Log.d(LOG_TAG, "The avatar has been uploaded, update the room avatar");
                                    mRoom.updateAvatarUrl(contentUri, mUpdateCallback);
                                }
                            });
                        }
                    });
                }
            }
        }
    }

    /**
     * Display the loading view in the parent activity layout.
     * This view is disabled/enabled to achieve a waiting screen.
     */
    private void displayLoadingView() {
        Activity parentActivity = getActivity();
        if (null != parentActivity) {
            parentActivity.runOnUiThread(new Runnable() {
                public void run() {

                    // disable the fragment container view to disable preferences access
                    //enablePreferenceWidgets(false);

                    // disable preference screen during server updates
                    if (null != mParentFragmentContainerView)
                        mParentFragmentContainerView.setEnabled(false);

                    // display the loading progress bar screen
                    if (null != mParentLoadingView) {
                        mParentLoadingView.setVisibility(View.VISIBLE);
                    }
                }
            });
        }
    }

    /**
     * Hide the loading progress bar screen and
     * update the UI if required.
     */
    private void hideLoadingView(boolean aIsUiRefreshRequired) {
        getActivity().runOnUiThread(new Runnable() {
            public void run() {

                // enable preference screen after server updates finished
                if (null != mParentFragmentContainerView)
                    mParentFragmentContainerView.setEnabled(true);

                // enable preference widgets
                //enablePreferenceWidgets(true);

                if (null != mParentLoadingView) {
                    mParentLoadingView.setVisibility(View.GONE);
                }
            }
        });

        if (aIsUiRefreshRequired) {
            updateUiOnUiThread();
        }
    }

    //================================================================================
    // Banned members management
    //================================================================================

    /**
     * Refresh the banned users list.
     */
    private void refreshBannedMembersList() {
        ArrayList<RoomMember> bannedMembers = new ArrayList<>();
        Collection<RoomMember> members = mRoom.getMembers();

        if (null != members) {
            for (RoomMember member : members) {
                if (TextUtils.equals(member.membership, RoomMember.MEMBERSHIP_BAN)) {
                    bannedMembers.add(member);
                }
            }
        }

        Collections.sort(bannedMembers, new Comparator<RoomMember>() {
            @Override
            public int compare(RoomMember m1, RoomMember m2) {
                return m1.getUserId().toLowerCase(VectorApp.getApplicationLocale()).compareTo(m2.getUserId().toLowerCase(VectorApp.getApplicationLocale()));
            }
        });

        PreferenceScreen preferenceScreen = getPreferenceScreen();

        preferenceScreen.removePreference(mBannedMembersSettingsCategoryDivider);
        preferenceScreen.removePreference(mBannedMembersSettingsCategory);
        mBannedMembersSettingsCategory.removeAll();

        if (bannedMembers.size() > 0) {
            preferenceScreen.addPreference(mBannedMembersSettingsCategoryDivider);
            preferenceScreen.addPreference(mBannedMembersSettingsCategory);

            for (RoomMember member : bannedMembers) {
                VectorCustomActionEditTextPreference preference = new VectorCustomActionEditTextPreference(getActivity());

                final String userId = member.getUserId();

                preference.setTitle(userId);
                preference.setKey(BANNED_PREFERENCE_KEY_BASE + userId);

                preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                    @Override
                    public boolean onPreferenceClick(Preference preference) {
                        Intent startRoomInfoIntent = new Intent(getActivity(), VectorMemberDetailsActivity.class);
                        startRoomInfoIntent.putExtra(VectorMemberDetailsActivity.EXTRA_MEMBER_ID, userId);
                        startRoomInfoIntent.putExtra(VectorMemberDetailsActivity.EXTRA_ROOM_ID, mRoom.getRoomId());
                        startRoomInfoIntent.putExtra(VectorMemberDetailsActivity.EXTRA_MATRIX_ID, mSession.getCredentials().userId);
                        getActivity().startActivity(startRoomInfoIntent);
                        return false;
                    }
                });

                mBannedMembersSettingsCategory.addPreference(preference);
            }
        }
    }

    //================================================================================
    // flair management
    //================================================================================

    private final ApiCallback mFlairUpdatesCallback = new ApiCallback<Void>() {
        @Override
        public void onSuccess(Void info) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    hideLoadingView(false);
                    refreshFlair();
                }
            });
        }

        /**
         * Error management.
         * @param errorMessage the error message
         */
        private void onError(final String errorMessage) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(getActivity(), errorMessage, Toast.LENGTH_SHORT).show();
                    hideLoadingView(false);
                    refreshFlair();
                }
            });
        }

        @Override
        public void onNetworkError(Exception e) {
            onError(e.getLocalizedMessage());
        }

        @Override
        public void onMatrixError(MatrixError e) {
            onError(e.getLocalizedMessage());
        }

        @Override
        public void onUnexpectedError(Exception e) {
            onError(e.getLocalizedMessage());
        }
    };

    /**
     * Tells if the current user can updates the related group aka flairs
     *
     * @return true if the user is allowed.
     */
    private boolean canUpdateFlair() {
        boolean canUpdateAliases = false;

        PowerLevels powerLevels = mRoom.getLiveState().getPowerLevels();

        if (null != powerLevels) {
            int powerLevel = powerLevels.getUserPowerLevel(mSession.getMyUserId());
            canUpdateAliases = powerLevel >= powerLevels.minimumPowerLevelForSendingEventAsStateEvent(Event.EVENT_TYPE_STATE_RELATED_GROUPS);
        }

        return canUpdateAliases;
    }

    /**
     * Refresh the flair list
     */
    private void refreshFlair() {
        final List<String> groups = mRoom.getLiveState().getRelatedGroups();
        Collections.sort(groups, String.CASE_INSENSITIVE_ORDER);

        mFlairSettingsCategory.removeAll();

        if (!groups.isEmpty()) {
            for (final String groupId : groups) {
                VectorCustomActionEditTextPreference preference = new VectorCustomActionEditTextPreference(getActivity());
                preference.setTitle(groupId);
                preference.setKey(FLAIR_PREFERENCE_KEY_BASE + groupId);

                preference.setOnPreferenceLongClickListener(new VectorCustomActionEditTextPreference.OnPreferenceLongClickListener() {
                    @Override
                    public boolean onPreferenceLongClick(Preference preference) {
                        getActivity().runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                displayLoadingView();
                                mRoom.removeRelatedGroup(groupId, mFlairUpdatesCallback);
                            }
                        });

                        return true;
                    }
                });
                mFlairSettingsCategory.addPreference(preference);
            }
        } else {
            VectorCustomActionEditTextPreference preference = new VectorCustomActionEditTextPreference(getActivity());
            preference.setTitle(getString(R.string.room_settings_no_flair));
            preference.setKey(FLAIR_PREFERENCE_KEY_BASE + "no_flair");

            mFlairSettingsCategory.addPreference(preference);
        }

        if (canUpdateFlair()) {
            // display the "add addresses" entry
            EditTextPreference addAddressPreference = new EditTextPreference(getActivity());
            addAddressPreference.setTitle(R.string.room_settings_add_new_group);
            addAddressPreference.setDialogTitle(R.string.room_settings_add_new_group);
            addAddressPreference.setKey(FLAIR_PREFERENCE_KEY_BASE + "__add");
            addAddressPreference.setIcon(CommonActivityUtils.tintDrawable(getActivity(), ContextCompat.getDrawable(getActivity(), R.drawable.ic_add_black), R.attr.settings_icon_tint_color));

            addAddressPreference.setOnPreferenceChangeListener(
                    new Preference.OnPreferenceChangeListener() {
                        @Override
                        public boolean onPreferenceChange(Preference preference, Object newValue) {
                            final String groupId = ((String) newValue).trim();

                            // ignore empty alias
                            if (!TextUtils.isEmpty(groupId)) {
                                if (!MXSession.isGroupId(groupId)) {
                                    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                                    builder.setTitle(R.string.room_settings_invalid_group_format_dialog_title);
                                    builder.setMessage(getString(R.string.room_settings_invalid_group_format_dialog_body, groupId));
                                    builder.setPositiveButton(R.string.ok, null);
                                    AlertDialog dialog = builder.create();
                                    dialog.show();
                                } else if (!groups.contains(groupId)) {
                                    getActivity().runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            displayLoadingView();
                                            mRoom.addRelatedGroup(groupId, mFlairUpdatesCallback);
                                        }
                                    });
                                }
                            }
                            return false;
                        }
                    });

            mFlairSettingsCategory.addPreference(addAddressPreference);
        }
    }

    //================================================================================
    // Aliases management
    //================================================================================

    private final ApiCallback mAliasUpdatesCallback = new ApiCallback<Void>() {
        @Override
        public void onSuccess(Void info) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    hideLoadingView(false);
                    refreshAddresses();
                }
            });
        }

        /**
         * Error management.
         * @param errorMessage the error message
         */
        private void onError(final String errorMessage) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(getActivity(), errorMessage, Toast.LENGTH_SHORT).show();
                    hideLoadingView(false);
                    refreshAddresses();
                }
            });
        }

        @Override
        public void onNetworkError(Exception e) {
            onError(e.getLocalizedMessage());
        }

        @Override
        public void onMatrixError(MatrixError e) {
            onError(e.getLocalizedMessage());
        }

        @Override
        public void onUnexpectedError(Exception e) {
            onError(e.getLocalizedMessage());
        }
    };

    /**
     * Manage the long click on an address.
     *
     * @param roomAlias  the room alias.
     * @param anchorView the popup menu anchor view.
     */
    @SuppressLint("NewApi")
    private void onAddressLongClick(final String roomAlias, final View anchorView) {
        Context context = getActivity();
        final PopupMenu popup = (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) ? new PopupMenu(context, anchorView, Gravity.END) : new PopupMenu(context, anchorView);

        popup.getMenuInflater().inflate(R.menu.vector_room_settings_addresses, popup.getMenu());

        // force to display the icons
        try {
            Field[] fields = popup.getClass().getDeclaredFields();
            for (Field field : fields) {
                if ("mPopup".equals(field.getName())) {
                    field.setAccessible(true);
                    Object menuPopupHelper = field.get(popup);
                    Class<?> classPopupHelper = Class.forName(menuPopupHelper.getClass().getName());
                    Method setForceIcons = classPopupHelper.getMethod("setForceShowIcon", boolean.class);
                    setForceIcons.invoke(menuPopupHelper, true);
                    break;
                }
            }
        } catch (Exception e) {
            Log.e(LOG_TAG, "onMessageClick : force to display the icons failed " + e.getLocalizedMessage());
        }

        Menu menu = popup.getMenu();
        CommonActivityUtils.tintMenuIcons(menu, ThemeUtils.getColor(context, R.attr.icon_tint_on_light_action_bar_color));

        String canonicalAlias = mRoom.getLiveState().alias;
        boolean canUpdateAliases = canUpdateAliases();

        menu.findItem(R.id.ic_action_vector_delete_alias).setVisible(canUpdateAliases);
        menu.findItem(R.id.ic_action_vector_set_as_main_address).setVisible(canUpdateAliases && !TextUtils.equals(roomAlias, canonicalAlias));
        menu.findItem(R.id.ic_action_vector_unset_main_address).setVisible(canUpdateAliases && TextUtils.equals(roomAlias, canonicalAlias));

        // display the menu
        popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(final MenuItem item) {
                if (item.getItemId() == R.id.ic_action_vector_unset_main_address) {
                    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                    builder.setMessage(R.string.room_settings_addresses_disable_main_address_prompt_msg);
                    builder.setTitle(R.string.room_settings_addresses_disable_main_address_prompt_title);

                    builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            displayLoadingView();
                            mRoom.updateCanonicalAlias(null, mAliasUpdatesCallback);
                        }
                    });

                    builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            // nothing
                        }
                    });

                    AlertDialog dialog = builder.create();
                    dialog.show();
                } else if (item.getItemId() == R.id.ic_action_vector_set_as_main_address) {
                    displayLoadingView();
                    mRoom.updateCanonicalAlias(roomAlias, mAliasUpdatesCallback);
                } else if (item.getItemId() == R.id.ic_action_vector_delete_alias) {
                    displayLoadingView();
                    mRoom.removeAlias(roomAlias, new ApiCallback<Void>() {
                        @Override
                        public void onSuccess(Void info) {
                            // when there is only one alias, it becomes the main alias.
                            if (mRoom.getAliases().size() == 1) {
                                mRoom.updateCanonicalAlias(mRoom.getAliases().get(0), mAliasUpdatesCallback);
                            } else {
                                mAliasUpdatesCallback.onSuccess(info);
                            }
                        }

                        @Override
                        public void onNetworkError(Exception e) {
                            mAliasUpdatesCallback.onNetworkError(e);
                        }

                        @Override
                        public void onMatrixError(MatrixError e) {
                            mAliasUpdatesCallback.onMatrixError(e);
                        }

                        @Override
                        public void onUnexpectedError(Exception e) {
                            mAliasUpdatesCallback.onUnexpectedError(e);
                        }
                    });
                } else if (item.getItemId() == R.id.ic_action_vector_room_url) {
                    VectorUtils.copyToClipboard(getActivity(), VectorUtils.getPermalink(roomAlias, null));
                } else {
                    VectorUtils.copyToClipboard(getActivity(), roomAlias);
                }

                return true;
            }
        });

        popup.show();
    }

    /**
     * Tells if the current user can updates the room aliases.
     *
     * @return true if the user is allowed.
     */
    private boolean canUpdateAliases() {
        boolean canUpdateAliases = false;

        PowerLevels powerLevels = mRoom.getLiveState().getPowerLevels();

        if (null != powerLevels) {
            int powerLevel = powerLevels.getUserPowerLevel(mSession.getMyUserId());
            canUpdateAliases = powerLevel >= powerLevels.minimumPowerLevelForSendingEventAsStateEvent(Event.EVENT_TYPE_STATE_ROOM_ALIASES);
        }

        return canUpdateAliases;
    }

    /**
     * Refresh the addresses section
     */
    private void refreshAddresses() {
        final String localSuffix = ":" + mSession.getHomeServerConfig().getHomeserverUri().getHost();
        final String canonicalAlias = mRoom.getLiveState().alias;
        final ArrayList<String> aliases = new ArrayList<>(mRoom.getAliases());

        // remove the displayed preferences
        mAddressesSettingsCategory.removeAll();

        if (0 == aliases.size()) {
            AddressPreference preference = new AddressPreference(getActivity());
            preference.setTitle(getString(R.string.room_settings_addresses_no_local_addresses));
            preference.setKey(NO_LOCAL_ADDRESS_PREFERENCE_KEY);
            mAddressesSettingsCategory.addPreference(preference);
        } else {
            ArrayList<String> localAliases = new ArrayList<>();
            ArrayList<String> remoteAliases = new ArrayList<>();

            for (String alias : aliases) {
                if (alias.endsWith(localSuffix)) {
                    localAliases.add(alias);
                } else {
                    remoteAliases.add(alias);
                }
            }

            // the local aliases are displayed first in the list
            aliases.clear();
            aliases.addAll(localAliases);
            aliases.addAll(remoteAliases);

            int index = 0;

            for (String alias : aliases) {
                AddressPreference preference = new AddressPreference(getActivity());
                preference.setTitle(alias);
                preference.setKey(ADDRESSES_PREFERENCE_KEY_BASE + index);
                preference.setMainIconVisible(TextUtils.equals(alias, canonicalAlias));

                final String fAlias = alias;
                final AddressPreference fAddressPreference = preference;

                preference.setOnPreferenceLongClickListener(new VectorCustomActionEditTextPreference.OnPreferenceLongClickListener() {
                    @Override
                    public boolean onPreferenceLongClick(Preference preference) {
                        onAddressLongClick(fAlias, fAddressPreference.getMainIconView());
                        return true;
                    }
                });

                mAddressesSettingsCategory.addPreference(preference);
                index++;
            }
        }

        if (canUpdateAliases()) {
            // display the "add addresses" entry
            EditTextPreference addAddressPreference = new EditTextPreference(getActivity());
            addAddressPreference.setTitle(R.string.room_settings_addresses_add_new_address);
            addAddressPreference.setDialogTitle(R.string.room_settings_addresses_add_new_address);
            addAddressPreference.setKey(ADD_ADDRESSES_PREFERENCE_KEY);
            addAddressPreference.setIcon(CommonActivityUtils.tintDrawable(getActivity(), ContextCompat.getDrawable(getActivity(), R.drawable.ic_add_black), R.attr.settings_icon_tint_color));

            addAddressPreference.setOnPreferenceChangeListener(
                    new Preference.OnPreferenceChangeListener() {
                        @Override
                        public boolean onPreferenceChange(Preference preference, Object newValue) {
                            final String newAddress = ((String) newValue).trim();

                            // ignore empty alias
                            if (!TextUtils.isEmpty(newAddress)) {
                                if (!MXSession.isRoomAlias(newAddress)) {
                                    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                                    builder.setTitle(R.string.room_settings_addresses_invalid_format_dialog_title);
                                    builder.setMessage(getString(R.string.room_settings_addresses_invalid_format_dialog_body, newAddress));

                                    builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                        }
                                    });

                                    AlertDialog dialog = builder.create();
                                    dialog.show();
                                } else if (aliases.indexOf(newAddress) < 0) {
                                    getActivity().runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            displayLoadingView();
                                            mRoom.addAlias(newAddress, new ApiCallback<Void>() {
                                                @Override
                                                public void onSuccess(Void info) {
                                                    // when there is only one alias, it becomes the main alias.
                                                    if (mRoom.getAliases().size() == 1) {
                                                        mRoom.updateCanonicalAlias(mRoom.getAliases().get(0), mAliasUpdatesCallback);
                                                    } else {
                                                        mAliasUpdatesCallback.onSuccess(info);
                                                    }
                                                }

                                                @Override
                                                public void onNetworkError(Exception e) {
                                                    mAliasUpdatesCallback.onNetworkError(e);
                                                }

                                                @Override
                                                public void onMatrixError(MatrixError e) {
                                                    mAliasUpdatesCallback.onMatrixError(e);
                                                }

                                                @Override
                                                public void onUnexpectedError(Exception e) {
                                                    mAliasUpdatesCallback.onUnexpectedError(e);
                                                }
                                            });
                                        }
                                    });
                                }
                            }
                            return false;
                        }
                    });

            mAddressesSettingsCategory.addPreference(addAddressPreference);
        }
    }


    /**
     * Refresh the addresses section
     */
    private void refreshEndToEnd() {
        // encrypt to unverified devices
        final CheckBoxPreference sendToUnverifiedDevicesPref = (CheckBoxPreference) findPreference(getString(R.string.room_settings_never_send_to_unverified_devices_title));

        // reported by GA
        if (null == sendToUnverifiedDevicesPref) {
            Log.e(LOG_TAG, "## refreshEndToEnd() : sendToUnverifiedDevicesPref is null");
            return;
        }

        // test if the crypto is
        if (null == mSession.getCrypto()) {
            mAdvandceSettingsCategory.removePreference(sendToUnverifiedDevicesPref);
        } else if (null != sendToUnverifiedDevicesPref) {
            if (mRoom.isEncrypted()) {
                sendToUnverifiedDevicesPref.setChecked(false);

                mSession.getCrypto().getGlobalBlacklistUnverifiedDevices(
                        new SimpleApiCallback<Boolean>() {
                            @Override
                            public void onSuccess(final Boolean sendToVerifiedDevicesInAnyRoom) {
                                mSession.getCrypto().isRoomBlacklistUnverifiedDevices(mRoom.getRoomId(), new SimpleApiCallback<Boolean>() {
                                    @Override
                                    public void onSuccess(final Boolean sendToVerifiedDevicesInRoom) {
                                        sendToUnverifiedDevicesPref.setChecked(sendToVerifiedDevicesInRoom || sendToVerifiedDevicesInAnyRoom);
                                        sendToUnverifiedDevicesPref.setEnabled(!sendToVerifiedDevicesInAnyRoom);
                                    }
                                });
                            }
                        }
                );

            } else if (null != sendToUnverifiedDevicesPref) {
                mAdvandceSettingsCategory.removePreference(sendToUnverifiedDevicesPref);
            }

            sendToUnverifiedDevicesPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                @Override
                public boolean onPreferenceClick(Preference preference) {
                    mSession.getCrypto().isRoomBlacklistUnverifiedDevices(mRoom.getRoomId(), new SimpleApiCallback<Boolean>() {
                        @Override
                        public void onSuccess(Boolean status) {
                            if (sendToUnverifiedDevicesPref.isChecked() != status) {
                                SimpleApiCallback<Void> callback = new SimpleApiCallback<Void>() {
                                    @Override
                                    public void onSuccess(Void info) {
                                    }
                                };

                                if (sendToUnverifiedDevicesPref.isChecked()) {
                                    mSession.getCrypto().setRoomBlacklistUnverifiedDevices(mRoom.getRoomId(), callback);
                                } else {
                                    mSession.getCrypto().setRoomUnblacklistUnverifiedDevices(mRoom.getRoomId(), callback);
                                }
                            }
                        }
                    });

                    return true;
                }
            });
        }

        final String key = PREF_KEY_ENCRYPTION + mRoom.getRoomId();

        // remove the displayed preferences
        Preference e2ePref = mAdvandceSettingsCategory.findPreference(key);

        if (null != e2ePref) {
            mAdvandceSettingsCategory.removePreference(e2ePref);
        }

        // remove the preference because it might switch from a SwitchPreference to  VectorCustomActionEditTextPreference
        final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
        SharedPreferences.Editor editor = preferences.edit();
        editor.remove(key);
        editor.commit();

        if (mRoom.isEncrypted()) {
            VectorCustomActionEditTextPreference isEncryptedPreference = new VectorCustomActionEditTextPreference(getActivity());
            isEncryptedPreference.setTitle(R.string.room_settings_addresses_e2e_enabled);
            isEncryptedPreference.setKey(key);
            isEncryptedPreference.setIcon(getResources().getDrawable(R.drawable.e2e_verified));
            mAdvandceSettingsCategory.addPreference(isEncryptedPreference);
        } else {
            PowerLevels powerLevels = mRoom.getLiveState().getPowerLevels();
            int myPowerLevel = -1;
            int minimumPowerLevel = 0;

            if (null != powerLevels) {
                myPowerLevel = powerLevels.getUserPowerLevel(mSession.getMyUserId());
                minimumPowerLevel = powerLevels.minimumPowerLevelForSendingEventAsStateEvent(Event.EVENT_TYPE_MESSAGE_ENCRYPTION);
            }

            // Test if the user has enough power levels to enable the crypto is in this room
            if (myPowerLevel < minimumPowerLevel) {
                VectorCustomActionEditTextPreference isEncryptedPreference = new VectorCustomActionEditTextPreference(getActivity());
                isEncryptedPreference.setTitle(R.string.room_settings_addresses_e2e_disabled);
                isEncryptedPreference.setKey(key);
                isEncryptedPreference.setIcon(CommonActivityUtils.tintDrawable(getActivity(), getResources().getDrawable(R.drawable.e2e_unencrypted), R.attr.settings_icon_tint_color));
                mAdvandceSettingsCategory.addPreference(isEncryptedPreference);
            } else if (mSession.isCryptoEnabled()) {
                final VectorSwitchPreference encryptSwitchPreference = new VectorSwitchPreference(getActivity());
                encryptSwitchPreference.setTitle(R.string.room_settings_addresses_e2e_encryption_warning);
                encryptSwitchPreference.setKey(key);
                encryptSwitchPreference.setIcon(CommonActivityUtils.tintDrawable(getActivity(), getResources().getDrawable(R.drawable.e2e_unencrypted), R.attr.settings_icon_tint_color));
                encryptSwitchPreference.setChecked(false);
                mAdvandceSettingsCategory.addPreference(encryptSwitchPreference);

                encryptSwitchPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
                    @Override
                    public boolean onPreferenceChange(Preference preference, Object newValueAsVoid) {
                        boolean newValue = (boolean) newValueAsVoid;

                        if (newValue != mRoom.isEncrypted()) {
                            new AlertDialog.Builder(getActivity())
                                    .setTitle(R.string.room_settings_addresses_e2e_prompt_title)
                                    .setMessage(R.string.room_settings_addresses_e2e_prompt_message)
                                    .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            dialog.dismiss();

                                            displayLoadingView();
                                            mRoom.enableEncryptionWithAlgorithm(MXCryptoAlgorithms.MXCRYPTO_ALGORITHM_MEGOLM, new ApiCallback<Void>() {

                                                private void onDone() {
                                                    hideLoadingView(false);
                                                    refreshEndToEnd();
                                                }

                                                @Override
                                                public void onSuccess(Void info) {
                                                    onDone();
                                                }

                                                @Override
                                                public void onNetworkError(Exception e) {
                                                    onDone();
                                                }

                                                @Override
                                                public void onMatrixError(MatrixError e) {
                                                    onDone();
                                                }

                                                @Override
                                                public void onUnexpectedError(Exception e) {
                                                    onDone();
                                                }
                                            });

                                        }
                                    })
                                    .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            dialog.dismiss();
                                            encryptSwitchPreference.setChecked(false);
                                        }
                                    })
                                    .create()
                                    .show();
                        }
                        return true;
                    }
                });

            }
        }
    }
}
