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

import android.app.Activity;
import android.app.Fragment;
import android.app.LoaderManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;
import android.content.Loader;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.util.ArrayMap;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ContentLoadingProgressBar;
import android.support.v7.widget.Toolbar;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.android.contacts.compat.CompatUtils;
import com.android.contacts.database.SimContactDao;
import com.android.contacts.editor.AccountHeaderPresenter;
import com.android.contacts.model.AccountTypeManager;
import com.android.contacts.model.SimCard;
import com.android.contacts.model.SimContact;
import com.android.contacts.model.account.AccountInfo;
import com.android.contacts.model.account.AccountWithDataSet;
import com.android.contacts.preference.ContactsPreferences;
import com.android.contacts.util.concurrent.ContactsExecutors;
import com.android.contacts.util.concurrent.ListenableFutureLoader;
import com.google.common.base.Function;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;

/**
 * Dialog that presents a list of contacts from a SIM card that can be imported into a selected
 * account
 */
public class SimImportFragment extends Fragment
        implements LoaderManager.LoaderCallbacks<SimImportFragment.LoaderResult>,
        AdapterView.OnItemClickListener, AbsListView.OnScrollListener {

    private static final String KEY_SUFFIX_SELECTED_IDS = "_selectedIds";
    private static final String ARG_SUBSCRIPTION_ID = "subscriptionId";

    private ContactsPreferences mPreferences;
    private AccountTypeManager mAccountTypeManager;
    private SimContactAdapter mAdapter;
    private View mAccountHeaderContainer;
    private AccountHeaderPresenter mAccountHeaderPresenter;
    private float mAccountScrolledElevationPixels;
    private ContentLoadingProgressBar mLoadingIndicator;
    private Toolbar mToolbar;
    private ListView mListView;
    private View mImportButton;

    private Bundle mSavedInstanceState;

    private final Map<AccountWithDataSet, long[]> mPerAccountCheckedIds = new ArrayMap<>();

    private int mSubscriptionId;

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

        mSavedInstanceState = savedInstanceState;
        mPreferences = new ContactsPreferences(getContext());
        mAccountTypeManager = AccountTypeManager.getInstance(getActivity());
        mAdapter = new SimContactAdapter(getActivity());

        final Bundle args = getArguments();
        mSubscriptionId = args == null ? SimCard.NO_SUBSCRIPTION_ID :
                args.getInt(ARG_SUBSCRIPTION_ID, SimCard.NO_SUBSCRIPTION_ID);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        getLoaderManager().initLoader(0, null, this);
    }

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

        mAccountHeaderContainer = view.findViewById(R.id.account_header_container);
        mAccountScrolledElevationPixels = getResources()
                .getDimension(R.dimen.contact_list_header_elevation);
        mAccountHeaderPresenter = new AccountHeaderPresenter(
                mAccountHeaderContainer);
        if (savedInstanceState != null) {
            mAccountHeaderPresenter.onRestoreInstanceState(savedInstanceState);
        } else {
            // Default may be null in which case the first account in the list will be selected
            // after they are loaded.
            mAccountHeaderPresenter.setCurrentAccount(mPreferences.getDefaultAccount());
        }
        mAccountHeaderPresenter.setObserver(new AccountHeaderPresenter.Observer() {
            @Override
            public void onChange(AccountHeaderPresenter sender) {
                rememberSelectionsForCurrentAccount();
                mAdapter.setAccount(sender.getCurrentAccount());
                showSelectionsForCurrentAccount();
                updateToolbarWithCurrentSelections();
            }
        });
        mAdapter.setAccount(mAccountHeaderPresenter.getCurrentAccount());

        mListView = (ListView) view.findViewById(R.id.list);
        mListView.setOnScrollListener(this);
        mListView.setAdapter(mAdapter);
        mListView.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
        mListView.setOnItemClickListener(this);
        mImportButton = view.findViewById(R.id.import_button);
        mImportButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                importCurrentSelections();
                // Do we wait for import to finish?
                getActivity().setResult(Activity.RESULT_OK);
                getActivity().finish();
            }
        });

        mToolbar = (Toolbar) view.findViewById(R.id.toolbar);
        mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getActivity().setResult(Activity.RESULT_CANCELED);
                getActivity().finish();
            }
        });

        mLoadingIndicator = (ContentLoadingProgressBar) view.findViewById(R.id.loading_progress);

        return view;
    }

    private void rememberSelectionsForCurrentAccount() {
        final AccountWithDataSet current = mAdapter.getAccount();
        if (current == null) {
            return;
        }
        final long[] ids = mListView.getCheckedItemIds();
        Arrays.sort(ids);
        mPerAccountCheckedIds.put(current, ids);
    }

    private void showSelectionsForCurrentAccount() {
        final long[] ids = mPerAccountCheckedIds.get(mAdapter.getAccount());
        if (ids == null) {
            selectAll();
            return;
        }
        for (int i = 0, len = mListView.getCount(); i < len; i++) {
            mListView.setItemChecked(i,
                    Arrays.binarySearch(ids, mListView.getItemIdAtPosition(i)) >= 0);
        }
    }

    private void selectAll() {
        for (int i = 0, len = mListView.getCount(); i < len; i++) {
            mListView.setItemChecked(i, true);
        }
    }

    private void updateToolbarWithCurrentSelections() {
        // The ListView keeps checked state for items that are disabled but we only want  to
        // consider items that don't exist in the current account when updating the toolbar
        int importableCount = 0;
        final SparseBooleanArray checked = mListView.getCheckedItemPositions();
        for (int i = 0; i < checked.size(); i++) {
            if (checked.valueAt(i) && !mAdapter.existsInCurrentAccount(checked.keyAt(i))) {
                importableCount++;
            }
        }

        if (importableCount == 0) {
            mImportButton.setVisibility(View.GONE);
            mToolbar.setTitle(R.string.sim_import_title_none_selected);
        } else {
            mToolbar.setTitle(String.valueOf(importableCount));
            mImportButton.setVisibility(View.VISIBLE);
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        if (mAdapter.isEmpty() && getLoaderManager().getLoader(0).isStarted()) {
            mLoadingIndicator.show();
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        rememberSelectionsForCurrentAccount();
        // We'll restore this manually so we don't need the list to preserve it's own state.
        mListView.clearChoices();
        super.onSaveInstanceState(outState);
        mAccountHeaderPresenter.onSaveInstanceState(outState);
        saveAdapterSelectedStates(outState);
    }

    @Override
    public Loader<LoaderResult> onCreateLoader(int id, Bundle args) {
        return new SimContactLoader(getContext(), mSubscriptionId);
    }

    @Override
    public void onLoadFinished(Loader<LoaderResult> loader,
            LoaderResult data) {
        mLoadingIndicator.hide();
        if (data == null) {
            return;
        }
        mAccountHeaderPresenter.setAccounts(data.accounts);
        restoreAdapterSelectedStates(data.accounts);
        mAdapter.setData(data);
        mListView.setEmptyView(getView().findViewById(R.id.empty_message));

        showSelectionsForCurrentAccount();
        updateToolbarWithCurrentSelections();
    }

    @Override
    public void onLoaderReset(Loader<LoaderResult> loader) {
    }

    private void restoreAdapterSelectedStates(List<AccountInfo> accounts) {
        if (mSavedInstanceState == null) {
            return;
        }

        for (AccountInfo account : accounts) {
            final long[] selections = mSavedInstanceState.getLongArray(
                    account.getAccount().stringify() + KEY_SUFFIX_SELECTED_IDS);
            mPerAccountCheckedIds.put(account.getAccount(), selections);
        }
        mSavedInstanceState = null;
    }

    private void saveAdapterSelectedStates(Bundle outState) {
        if (mAdapter == null) {
            return;
        }

        // Make sure the selections are up-to-date
        for (Map.Entry<AccountWithDataSet, long[]> entry : mPerAccountCheckedIds.entrySet()) {
            outState.putLongArray(entry.getKey().stringify() + KEY_SUFFIX_SELECTED_IDS,
                    entry.getValue());
        }
    }

    private void importCurrentSelections() {
        final SparseBooleanArray checked = mListView.getCheckedItemPositions();
        final ArrayList<SimContact> importableContacts = new ArrayList<>(checked.size());
        for (int i = 0; i < checked.size(); i++) {
            // It's possible for existing contacts to be "checked" but we only want to import the
            // ones that don't already exist
            if (checked.valueAt(i) && !mAdapter.existsInCurrentAccount(i)) {
                importableContacts.add(mAdapter.getItem(checked.keyAt(i)));
            }
        }
        SimImportService.startImport(getContext(), mSubscriptionId, importableContacts,
                mAccountHeaderPresenter.getCurrentAccount());
    }

    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        if (mAdapter.existsInCurrentAccount(position)) {
            Snackbar.make(getView(), R.string.sim_import_contact_exists_toast,
                    Snackbar.LENGTH_LONG).show();
        } else {
            updateToolbarWithCurrentSelections();
        }
    }

    public Context getContext() {
        if (CompatUtils.isMarshmallowCompatible()) {
            return super.getContext();
        }
        return getActivity();
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) { }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
            int totalItemCount) {
        int firstCompletelyVisibleItem = firstVisibleItem;
        if (view != null && view.getChildAt(0) != null && view.getChildAt(0).getTop() < 0) {
            firstCompletelyVisibleItem++;
        }

        if (firstCompletelyVisibleItem == 0) {
            ViewCompat.setElevation(mAccountHeaderContainer, 0);
        } else {
            ViewCompat.setElevation(mAccountHeaderContainer, mAccountScrolledElevationPixels);
        }
    }

    /**
     * Creates a fragment that will display contacts stored on the default SIM card
     */
    public static SimImportFragment newInstance() {
        return new SimImportFragment();
    }

    /**
     * Creates a fragment that will display the contacts stored on the SIM card that has the
     * provided subscriptionId
     */
    public static SimImportFragment newInstance(int subscriptionId) {
        final SimImportFragment fragment = new SimImportFragment();
        final Bundle args = new Bundle();
        args.putInt(ARG_SUBSCRIPTION_ID, subscriptionId);
        fragment.setArguments(args);
        return fragment;
    }

    private static class SimContactAdapter extends ArrayAdapter<SimContact> {
        private Map<AccountWithDataSet, Set<SimContact>> mExistingMap;
        private AccountWithDataSet mSelectedAccount;
        private LayoutInflater mInflater;

        public SimContactAdapter(Context context) {
            super(context, 0);
            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }

        @Override
        public long getItemId(int position) {
            // This can be called by the framework when the adapter hasn't been initialized for
            // checking the checked state of items. See b/33108913
            if (position < 0 || position >= getCount()) {
                return View.NO_ID;
            }
            return getItem(position).getId();
        }

        @Override
        public boolean hasStableIds() {
            return true;
        }

        @Override
        public int getViewTypeCount() {
            return 2;
        }

        @Override
        public int getItemViewType(int position) {
            return !existsInCurrentAccount(position) ? 0 : 1;
        }

        @NonNull
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            TextView text = (TextView) convertView;
            if (text == null) {
                final int layoutRes = existsInCurrentAccount(position) ?
                        R.layout.sim_import_list_item_disabled :
                        R.layout.sim_import_list_item;
                text = (TextView) mInflater.inflate(layoutRes, parent, false);
            }
            text.setText(getItemLabel(getItem(position)));

            return text;
        }

        public void setData(LoaderResult result) {
            clear();
            addAll(result.contacts);
            mExistingMap = result.accountsMap;
        }

        public void setAccount(AccountWithDataSet account) {
            mSelectedAccount = account;
            notifyDataSetChanged();
        }

        public AccountWithDataSet getAccount() {
            return mSelectedAccount;
        }

        public boolean existsInCurrentAccount(int position) {
            return existsInCurrentAccount(getItem(position));
        }

        public boolean existsInCurrentAccount(SimContact contact) {
            if (mSelectedAccount == null || !mExistingMap.containsKey(mSelectedAccount)) {
                return false;
            }
            return mExistingMap.get(mSelectedAccount).contains(contact);
        }

        private String getItemLabel(SimContact contact) {
            if (contact.hasName()) {
                return contact.getName();
            } else if (contact.hasPhone()) {
                return contact.getPhone();
            } else if (contact.hasEmails()) {
                return contact.getEmails()[0];
            } else {
                // This isn't really possible because we skip empty SIM contacts during loading
                return "";
            }
        }
    }


    private static class SimContactLoader extends ListenableFutureLoader<LoaderResult> {
        private SimContactDao mDao;
        private AccountTypeManager mAccountTypeManager;
        private final int mSubscriptionId;

        public SimContactLoader(Context context, int subscriptionId) {
            super(context, new IntentFilter(AccountTypeManager.BROADCAST_ACCOUNTS_CHANGED));
            mDao = SimContactDao.create(context);
            mAccountTypeManager = AccountTypeManager.getInstance(getContext());
            mSubscriptionId = subscriptionId;
        }

        @Override
        protected ListenableFuture<LoaderResult> loadData() {
            final ListenableFuture<List<Object>> future = Futures.<Object>allAsList(
                    mAccountTypeManager
                            .filterAccountsAsync(AccountTypeManager.writableFilter()),
                    ContactsExecutors.getSimReadExecutor().<Object>submit(
                            new Callable<Object>() {
                        @Override
                        public LoaderResult call() throws Exception {
                            return loadFromSim();
                        }
                    }));
            return Futures.transform(future, new Function<List<Object>, LoaderResult>() {
                @Override
                public LoaderResult apply(List<Object> input) {
                    final List<AccountInfo> accounts = (List<AccountInfo>) input.get(0);
                    final LoaderResult simLoadResult = (LoaderResult) input.get(1);
                    simLoadResult.accounts = accounts;
                    return simLoadResult;
                }
            });
        }

        private LoaderResult loadFromSim() {
            final SimCard sim = mDao.getSimBySubscriptionId(mSubscriptionId);
            LoaderResult result = new LoaderResult();
            if (sim == null) {
                result.contacts = new ArrayList<>();
                result.accountsMap = Collections.emptyMap();
                return result;
            }
            result.contacts = mDao.loadContactsForSim(sim);
            result.accountsMap = mDao.findAccountsOfExistingSimContacts(result.contacts);
            return result;
        }
    }

    public static class LoaderResult {
        public List<AccountInfo> accounts;
        public ArrayList<SimContact> contacts;
        public Map<AccountWithDataSet, Set<SimContact>> accountsMap;
    }
}
