/*
 * Copyright (C) 2019 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.car.telephony.common;

import android.content.Context;
import android.database.Cursor;
import android.provider.ContactsContract;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.Nullable;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;

/**
 * A singleton statically accessible helper class which pre-loads contacts list into memory so that
 * they can be accessed more easily and quickly.
 */
public class InMemoryPhoneBook implements Observer<List<Contact>> {
    private static final String TAG = "CD.InMemoryPhoneBook";
    private static final String KEY_FORMAT = "%s %s";
    private static InMemoryPhoneBook sInMemoryPhoneBook;

    private final Context mContext;
    private final AsyncQueryLiveData<List<Contact>> mContactListAsyncQueryLiveData;
    /**
     * A map to speed up phone number searching.
     */
    private final Map<I18nPhoneNumberWrapper, Contact> mPhoneNumberContactMap = new HashMap<>();
    /**
     * A map to look up contact by lookup key.
     */
    private final Map<String, Contact> mLookupKeyContactMap = new HashMap<>();
    private boolean mIsLoaded = false;

    /**
     * Initialize the globally accessible {@link InMemoryPhoneBook}. Returns the existing {@link
     * InMemoryPhoneBook} if already initialized. {@link #tearDown()} must be called before init to
     * reinitialize.
     */
    public static InMemoryPhoneBook init(Context context) {
        if (sInMemoryPhoneBook == null) {
            sInMemoryPhoneBook = new InMemoryPhoneBook(context);
            sInMemoryPhoneBook.onInit();
        }
        return get();
    }

    /**
     * Returns if the InMemoryPhoneBook is initialized. get() won't return null or throw if this is
     * true, but it doesn't indicate whether or not contacts are loaded yet.
     * <p>
     * See also: {@link #isLoaded()}
     */
    public static boolean isInitialized() {
        return sInMemoryPhoneBook != null;
    }

    /**
     * Get the global {@link InMemoryPhoneBook} instance.
     */
    public static InMemoryPhoneBook get() {
        if (sInMemoryPhoneBook != null) {
            return sInMemoryPhoneBook;
        } else {
            throw new IllegalStateException("Call init before get InMemoryPhoneBook");
        }
    }

    /**
     * Tears down the globally accessible {@link InMemoryPhoneBook}.
     */
    public static void tearDown() {
        sInMemoryPhoneBook.onTearDown();
        sInMemoryPhoneBook = null;
    }

    private InMemoryPhoneBook(Context context) {
        mContext = context;

        QueryParam contactListQueryParam = new QueryParam(
                ContactsContract.Data.CONTENT_URI,
                null,
                ContactsContract.Data.MIMETYPE + " = ? OR "
                        + ContactsContract.Data.MIMETYPE + " = ?",
                new String[]{
                        ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,
                        ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE},
                ContactsContract.Contacts.DISPLAY_NAME + " ASC ");
        mContactListAsyncQueryLiveData = new AsyncQueryLiveData<List<Contact>>(mContext,
                QueryParam.of(contactListQueryParam), Executors.newSingleThreadExecutor()) {
            @Override
            protected List<Contact> convertToEntity(Cursor cursor) {
                return onCursorLoaded(cursor);
            }
        };
    }

    private void onInit() {
        mContactListAsyncQueryLiveData.observeForever(this);
    }

    private void onTearDown() {
        mContactListAsyncQueryLiveData.removeObserver(this);
    }

    public boolean isLoaded() {
        return mIsLoaded;
    }

    /**
     * Returns a {@link LiveData} which monitors the contact list changes.
     */
    public LiveData<List<Contact>> getContactsLiveData() {
        return mContactListAsyncQueryLiveData;
    }

    /**
     * Looks up a {@link Contact} by the given phone number. Returns null if can't find a Contact or
     * the {@link InMemoryPhoneBook} is still loading.
     */
    @Nullable
    public Contact lookupContactEntry(String phoneNumber) {
        Log.v(TAG, String.format("lookupContactEntry: %s", phoneNumber));
        if (!isLoaded()) {
            Log.w(TAG, "looking up a contact while loading.");
        }

        if (TextUtils.isEmpty(phoneNumber)) {
            Log.w(TAG, "looking up an empty phone number.");
            return null;
        }

        I18nPhoneNumberWrapper i18nPhoneNumber = I18nPhoneNumberWrapper.Factory.INSTANCE.get(
                mContext, phoneNumber);
        return mPhoneNumberContactMap.get(i18nPhoneNumber);
    }

    /**
     * Looks up a {@link Contact} by the given lookup key and account name. Account name could be
     * null for locally added contacts. Returns null if can't find the contact entry.
     */
    @Nullable
    public Contact lookupContactByKey(String lookupKey, @Nullable String accountName) {
        if (!isLoaded()) {
            Log.w(TAG, "looking up a contact while loading.");
        }
        if (TextUtils.isEmpty(lookupKey)) {
            Log.w(TAG, "looking up an empty lookup key.");
            return null;
        }

        return mLookupKeyContactMap.get(getContactKey(lookupKey, accountName));
    }

    private List<Contact> onCursorLoaded(Cursor cursor) {
        Map<String, Contact> contactMap = new LinkedHashMap<>();
        List<Contact> contactList = new ArrayList<>();

        while (cursor.moveToNext()) {
            int accountNameColumn = cursor.getColumnIndex(
                    ContactsContract.RawContacts.ACCOUNT_NAME);
            int lookupKeyColumn = cursor.getColumnIndex(ContactsContract.Data.LOOKUP_KEY);
            String accountName = cursor.getString(accountNameColumn);
            String lookupKey = cursor.getString(lookupKeyColumn);
            String key = getContactKey(lookupKey, accountName);

            contactMap.put(key, Contact.fromCursor(mContext, cursor, contactMap.get(key)));
        }

        contactList.addAll(contactMap.values());

        mLookupKeyContactMap.clear();
        mLookupKeyContactMap.putAll(contactMap);

        for (Contact contact : contactList) {
            for (PhoneNumber phoneNumber : contact.getNumbers()) {
                mPhoneNumberContactMap.put(phoneNumber.getI18nPhoneNumberWrapper(), contact);
            }
        }
        return contactList;
    }

    @Override
    public void onChanged(List<Contact> contacts) {
        Log.d(TAG, "Contacts loaded:" + (contacts == null ? 0 : contacts.size()));
        mIsLoaded = true;
    }

    /**
     * Formats a key to identify a contact based the lookup key and the account name. Account Name
     * could be null and it will be handled by String.format().
     */
    private String getContactKey(String lookupKey, @Nullable String accountName) {
        String key = String.format(KEY_FORMAT, lookupKey, accountName);
        Log.d(TAG, "Contact key is: " + key);
        return key;
    }
}
