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

import android.annotation.TargetApi;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.Context;
import android.content.OperationApplicationException;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.RemoteException;
import android.provider.BaseColumns;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.RawContacts;
import android.support.annotation.VisibleForTesting;
import android.support.v4.util.ArrayMap;
import android.support.v4.util.ArraySet;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.SparseArray;

import com.android.contacts.R;
import com.android.contacts.common.compat.CompatUtils;
import com.android.contacts.common.model.SimCard;
import com.android.contacts.common.model.SimContact;
import com.android.contacts.common.model.account.AccountWithDataSet;
import com.android.contacts.common.util.PermissionsUtil;
import com.android.contacts.util.SharedPreferenceUtil;
import com.google.common.base.Joiner;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Provides data access methods for loading contacts from a SIM card and and migrating these
 * SIM contacts to a CP2 account.
 */
public class SimContactDao {
    private static final String TAG = "SimContactDao";

    // Maximum number of SIM contacts to import in a single ContentResolver.applyBatch call.
    // This is necessary to avoid TransactionTooLargeException when there are a large number of
    // contacts. This has been tested on Nexus 6 NME70B and is probably be conservative enough
    // to work on any phone.
    private static final int IMPORT_MAX_BATCH_SIZE = 300;

    // How many SIM contacts to consider in a single query. This prevents hitting the SQLite
    // query parameter limit.
    static final int QUERY_MAX_BATCH_SIZE = 100;

    // Set to true for manual testing on an emulator or phone without a SIM card
    // DO NOT SUBMIT if set to true
    private static final boolean USE_FAKE_INSTANCE = false;

    @VisibleForTesting
    public static final Uri ICC_CONTENT_URI = Uri.parse("content://icc/adn");

    public static String _ID = BaseColumns._ID;
    public static String NAME = "name";
    public static String NUMBER = "number";
    public static String EMAILS = "emails";

    private final Context mContext;
    private final ContentResolver mResolver;
    private final TelephonyManager mTelephonyManager;

    private SimContactDao(Context context) {
        mContext = context;
        mResolver = context.getContentResolver();
        mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    }


    public Context getContext() {
        return mContext;
    }

    public boolean canReadSimContacts() {
        // Require SIM_STATE_READY because the TelephonyManager methods related to SIM require
        // this state
        return hasTelephony() && hasPermissions() &&
                mTelephonyManager.getSimState() == TelephonyManager.SIM_STATE_READY;
    }

    public List<SimCard> getSimCards() {
        if (!canReadSimContacts()) {
            return Collections.emptyList();
        }
        final List<SimCard> sims = CompatUtils.isMSIMCompatible() ?
                getSimCardsFromSubscriptions() :
                Collections.singletonList(SimCard.create(mTelephonyManager,
                        mContext.getString(R.string.single_sim_display_label)));
        return SharedPreferenceUtil.restoreSimStates(mContext, sims);
    }

    public List<SimCard> getSimCardsWithContacts() {
        final List<SimCard> result = new ArrayList<>();
        for (SimCard sim : getSimCards()) {
            result.add(sim.withContacts(loadContactsForSim(sim)));
        }
        return result;
    }

    public ArrayList<SimContact> loadContactsForSim(SimCard sim) {
        if (sim.hasValidSubscriptionId()) {
            return loadSimContacts(sim.getSubscriptionId());
        }
        return loadSimContacts();
    }

    public ArrayList<SimContact> loadSimContacts(int subscriptionId) {
        return loadFrom(ICC_CONTENT_URI.buildUpon()
                .appendPath("subId")
                .appendPath(String.valueOf(subscriptionId))
                .build());
    }

    public ArrayList<SimContact> loadSimContacts() {
        return loadFrom(ICC_CONTENT_URI);
    }

    public ContentProviderResult[] importContacts(List<SimContact> contacts,
            AccountWithDataSet targetAccount)
            throws RemoteException, OperationApplicationException {
        if (contacts.size() < IMPORT_MAX_BATCH_SIZE) {
            return importBatch(contacts, targetAccount);
        }
        final List<ContentProviderResult> results = new ArrayList<>();
        for (int i = 0; i < contacts.size(); i += IMPORT_MAX_BATCH_SIZE) {
            results.addAll(Arrays.asList(importBatch(
                    contacts.subList(i, Math.min(contacts.size(), i + IMPORT_MAX_BATCH_SIZE)),
                    targetAccount)));
        }
        return results.toArray(new ContentProviderResult[results.size()]);
    }

    public void persistSimState(SimCard sim) {
        SharedPreferenceUtil.persistSimStates(mContext, Collections.singletonList(sim));
    }

    public void persistSimStates(List<SimCard> simCards) {
        SharedPreferenceUtil.persistSimStates(mContext, simCards);
    }

    public SimCard getFirstSimCard() {
        return getSimBySubscriptionId(SimCard.NO_SUBSCRIPTION_ID);
    }

    public SimCard getSimBySubscriptionId(int subscriptionId) {
        final List<SimCard> sims = SharedPreferenceUtil.restoreSimStates(mContext, getSimCards());
        if (subscriptionId == SimCard.NO_SUBSCRIPTION_ID && !sims.isEmpty()) {
            return sims.get(0);
        }
        for (SimCard sim : getSimCards()) {
            if (sim.getSubscriptionId() == subscriptionId) {
                return sim;
            }
        }
        return null;
    }

    /**
     * Finds SIM contacts that exist in CP2 and associates the account of the CP2 contact with
     * the SIM contact
     */
    public Map<AccountWithDataSet, Set<SimContact>> findAccountsOfExistingSimContacts(
            List<SimContact> contacts) {
        final Map<AccountWithDataSet, Set<SimContact>> result = new ArrayMap<>();
        for (int i = 0; i < contacts.size(); i += QUERY_MAX_BATCH_SIZE) {
            findAccountsOfExistingSimContacts(
                    contacts.subList(i, Math.min(contacts.size(), i + QUERY_MAX_BATCH_SIZE)),
                    result);
        }
        return result;
    }

    private void findAccountsOfExistingSimContacts(List<SimContact> contacts,
            Map<AccountWithDataSet, Set<SimContact>> result) {
        final Map<Long, List<SimContact>> rawContactToSimContact = new HashMap<>();
        Collections.sort(contacts, SimContact.compareByPhoneThenName());

        final Cursor dataCursor = queryRawContactsForSimContacts(contacts);

        try {
            while (dataCursor.moveToNext()) {
                final String number = DataQuery.getPhoneNumber(dataCursor);
                final String name = DataQuery.getDisplayName(dataCursor);

                final int index = SimContact.findByPhoneAndName(contacts, number, name);
                if (index < 0) {
                    continue;
                }
                final SimContact contact = contacts.get(index);
                final long id = DataQuery.getRawContactId(dataCursor);
                if (!rawContactToSimContact.containsKey(id)) {
                    rawContactToSimContact.put(id, new ArrayList<SimContact>());
                }
                rawContactToSimContact.get(id).add(contact);
            }
        } finally {
            dataCursor.close();
        }

        final Cursor accountsCursor = queryAccountsOfRawContacts(rawContactToSimContact.keySet());
        try {
            while (accountsCursor.moveToNext()) {
                final AccountWithDataSet account = AccountQuery.getAccount(accountsCursor);
                final long id = AccountQuery.getId(accountsCursor);
                if (!result.containsKey(account)) {
                    result.put(account, new ArraySet<SimContact>());
                }
                for (SimContact contact : rawContactToSimContact.get(id)) {
                    result.get(account).add(contact);
                }
            }
        } finally {
            accountsCursor.close();
        }
    }

    private ContentProviderResult[] importBatch(List<SimContact> contacts,
            AccountWithDataSet targetAccount)
            throws RemoteException, OperationApplicationException {
        final ArrayList<ContentProviderOperation> ops =
                createImportOperations(contacts, targetAccount);
        return mResolver.applyBatch(ContactsContract.AUTHORITY, ops);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1)
    private List<SimCard> getSimCardsFromSubscriptions() {
        final SubscriptionManager subscriptionManager = (SubscriptionManager)
                mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
        final List<SubscriptionInfo> subscriptions = subscriptionManager
                .getActiveSubscriptionInfoList();
        final ArrayList<SimCard> result = new ArrayList<>();
        for (SubscriptionInfo subscriptionInfo : subscriptions) {
            result.add(SimCard.create(subscriptionInfo));
        }
        return result;
    }

    private List<SimContact> getContactsForSim(SimCard sim) {
        final List<SimContact> contacts = sim.getContacts();
        return contacts != null ? contacts : loadContactsForSim(sim);
    }

    // See b/32831092
    // Sometimes the SIM contacts provider seems to get stuck if read from multiple threads
    // concurrently. So we just have a global lock around it to prevent potential issues.
    private static final Object SIM_READ_LOCK = new Object();
    private ArrayList<SimContact> loadFrom(Uri uri) {
        synchronized (SIM_READ_LOCK) {
            final Cursor cursor = mResolver.query(uri, null, null, null, null);

            try {
                return loadFromCursor(cursor);
            } finally {
                cursor.close();
            }
        }
    }

    private ArrayList<SimContact> loadFromCursor(Cursor cursor) {
        final int colId = cursor.getColumnIndex(_ID);
        final int colName = cursor.getColumnIndex(NAME);
        final int colNumber = cursor.getColumnIndex(NUMBER);
        final int colEmails = cursor.getColumnIndex(EMAILS);

        final ArrayList<SimContact> result = new ArrayList<>();

        while (cursor.moveToNext()) {
            final long id = cursor.getLong(colId);
            final String name = cursor.getString(colName);
            final String number = cursor.getString(colNumber);
            final String emails = cursor.getString(colEmails);

            final SimContact contact = new SimContact(id, name, number, parseEmails(emails));
            result.add(contact);
        }
        return result;
    }

    private Cursor queryRawContactsForSimContacts(List<SimContact> contacts) {
        final StringBuilder selectionBuilder = new StringBuilder();

        int phoneCount = 0;
        int nameCount = 0;
        for (SimContact contact : contacts) {
            if (contact.hasPhone()) {
                phoneCount++;
            } else if (contact.hasName()) {
                nameCount++;
            }
        }
        List<String> selectionArgs = new ArrayList<>(phoneCount + 1);

        selectionBuilder.append('(');
        selectionBuilder.append(Data.MIMETYPE).append("=? AND ");
        selectionArgs.add(Phone.CONTENT_ITEM_TYPE);

        selectionBuilder.append(Phone.NUMBER).append(" IN (")
                .append(Joiner.on(',').join(Collections.nCopies(phoneCount, '?')))
                .append(')');
        for (SimContact contact : contacts) {
            if (contact.hasPhone()) {
                selectionArgs.add(contact.getPhone());
            }
        }
        selectionBuilder.append(')');

        if (nameCount > 0) {
            selectionBuilder.append(" OR (");

            selectionBuilder.append(Data.MIMETYPE).append("=? AND ");
            selectionArgs.add(StructuredName.CONTENT_ITEM_TYPE);

            selectionBuilder.append(Data.DISPLAY_NAME).append(" IN (")
                    .append(Joiner.on(',').join(Collections.nCopies(nameCount, '?')))
                    .append(')');
            for (SimContact contact : contacts) {
                if (!contact.hasPhone() && contact.hasName()) {
                    selectionArgs.add(contact.getName());
                }
            }
            selectionBuilder.append(')');
        }

        return mResolver.query(Data.CONTENT_URI.buildUpon()
                        .appendQueryParameter(Data.VISIBLE_CONTACTS_ONLY, "true")
                        .build(),
                DataQuery.PROJECTION,
                selectionBuilder.toString(),
                selectionArgs.toArray(new String[selectionArgs.size()]),
                null);
    }

    private Cursor queryAccountsOfRawContacts(Set<Long> ids) {
        final StringBuilder selectionBuilder = new StringBuilder();

        final String[] args = new String[ids.size()];

        selectionBuilder.append(RawContacts._ID).append(" IN (")
                .append(Joiner.on(',').join(Collections.nCopies(args.length, '?')))
                .append(")");
        int i = 0;
        for (long id : ids) {
            args[i++] = String.valueOf(id);
        }
        return mResolver.query(RawContacts.CONTENT_URI,
                AccountQuery.PROJECTION,
                selectionBuilder.toString(),
                args,
                null);
    }

    private ArrayList<ContentProviderOperation> createImportOperations(List<SimContact> contacts,
            AccountWithDataSet targetAccount) {
        final ArrayList<ContentProviderOperation> ops = new ArrayList<>();
        for (SimContact contact : contacts) {
            contact.appendCreateContactOperations(ops, targetAccount);
        }
        return ops;
    }

    private String[] parseEmails(String emails) {
        return emails != null ? emails.split(",") : null;
    }

    private boolean hasTelephony() {
        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
    }

    private boolean hasPermissions() {
        return PermissionsUtil.hasContactsPermissions(mContext) &&
                PermissionsUtil.hasPhonePermissions(mContext);
    }

    public static SimContactDao create(Context context) {
        if (USE_FAKE_INSTANCE) {
            return new DebugImpl(context)
                    .addSimCard(new SimCard("fake-sim-id1", 1, "Fake Carrier",
                            "Card 1", "15095550101", "us").withContacts(
                            new SimContact(1, "Sim One", "15095550111", null),
                            new SimContact(2, "Sim Two", "15095550112", null),
                            new SimContact(3, "Sim Three", "15095550113", null),
                            new SimContact(4, "Sim Four", "15095550114", null),
                            new SimContact(5, "411 & more", "411", null)
                    ))
                    .addSimCard(new SimCard("fake-sim-id2", 2, "Carrier Two",
                            "Card 2", "15095550102", "us").withContacts(
                            new SimContact(1, "John Sim", "15095550121", null),
                            new SimContact(2, "Bob Sim", "15095550122", null),
                            new SimContact(3, "Mary Sim", "15095550123", null),
                            new SimContact(4, "Alice Sim", "15095550124", null),
                            new SimContact(5, "Sim Duplicate", "15095550121", null)
                    ));
        }
        return new SimContactDao(context);
    }

    // TODO remove this class and the USE_FAKE_INSTANCE flag once this code is not under
    // active development or anytime after 3/1/2017
    public static class DebugImpl extends SimContactDao {

        private List<SimCard> mSimCards = new ArrayList<>();
        private SparseArray<SimCard> mCardsBySubscription = new SparseArray<>();

        public DebugImpl(Context context) {
            super(context);
        }

        public DebugImpl addSimCard(SimCard sim) {
            mSimCards.add(sim);
            mCardsBySubscription.put(sim.getSubscriptionId(), sim);
            return this;
        }

        @Override
        public List<SimCard> getSimCards() {
            return SharedPreferenceUtil.restoreSimStates(getContext(), mSimCards);
        }

        @Override
        public ArrayList<SimContact> loadSimContacts() {
            return new ArrayList<>(mSimCards.get(0).getContacts());
        }

        @Override
        public ArrayList<SimContact> loadSimContacts(int subscriptionId) {
            return new ArrayList<>(mCardsBySubscription.get(subscriptionId).getContacts());
        }

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

    // Query used for detecting existing contacts that may match a SimContact.
    private static final class DataQuery {

        public static final String[] PROJECTION = new String[] {
                Data.RAW_CONTACT_ID, Phone.NUMBER, Data.DISPLAY_NAME, Data.MIMETYPE
        };

        public static final int RAW_CONTACT_ID = 0;
        public static final int PHONE_NUMBER = 1;
        public static final int DISPLAY_NAME = 2;
        public static final int MIMETYPE = 3;

        public static long getRawContactId(Cursor cursor) {
            return cursor.getLong(RAW_CONTACT_ID);
        }

        public static String getPhoneNumber(Cursor cursor) {
            return isPhoneNumber(cursor) ? cursor.getString(PHONE_NUMBER) : null;
        }

        public static String getDisplayName(Cursor cursor) {
            return cursor.getString(DISPLAY_NAME);
        }

        public static boolean isPhoneNumber(Cursor cursor) {
            return Phone.CONTENT_ITEM_TYPE.equals(cursor.getString(MIMETYPE));
        }
    }

    private static final class AccountQuery {
        public static final String[] PROJECTION = new String[] {
                RawContacts._ID, RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_TYPE,
                RawContacts.DATA_SET
        };

        public static long getId(Cursor cursor) {
            return cursor.getLong(0);
        }

        public static AccountWithDataSet getAccount(Cursor cursor) {
            return new AccountWithDataSet(cursor.getString(1), cursor.getString(2),
                    cursor.getString(3));
        }
    }
}
