/*
 * Copyright (C) 2014 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.interactions;

import android.content.AsyncTaskLoader;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.provider.Telephony;
import android.util.Log;

import com.android.contacts.compat.TelephonyThreadsCompat;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Loads the most recent sms between the passed in phone numbers.
 *
 * This is a two part process. The first step is retrieving the threadIds for each of the phone
 * numbers using fuzzy matching. The next step is to run another query against these threadIds
 * to retrieve the actual sms.
 */
public class SmsInteractionsLoader extends AsyncTaskLoader<List<ContactInteraction>> {

    private static final String TAG = SmsInteractionsLoader.class.getSimpleName();

    private String[] mPhoneNums;
    private int mMaxToRetrieve;
    private List<ContactInteraction> mData;

    /**
     * Loads a list of SmsInteraction from the supplied phone numbers.
     */
    public SmsInteractionsLoader(Context context, String[] phoneNums,
            int maxToRetrieve) {
        super(context);
        Log.v(TAG, "SmsInteractionsLoader");
        mPhoneNums = phoneNums;
        mMaxToRetrieve = maxToRetrieve;
    }

    @Override
    public List<ContactInteraction> loadInBackground() {
        Log.v(TAG, "loadInBackground");
        // Confirm the device has Telephony and numbers were provided before proceeding
        if (!getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
                || mPhoneNums == null || mPhoneNums.length == 0) {
            return Collections.emptyList();
        }

        // Retrieve the thread IDs
        List<String> threadIdStrings = new ArrayList<>();
        for (String phone : mPhoneNums) {
            // TODO: the phone numbers added to the ContactInteraction result should retain their
            // original formatting since TalkBack is not reading the normalized numbers correctly
            try {
                threadIdStrings.add(String.valueOf(
                        TelephonyThreadsCompat.getOrCreateThreadId(getContext(), phone)));
            } catch (Exception e) {
                // Do nothing. Telephony.Threads.getOrCreateThreadId() throws exceptions when
                // it can't find/create a threadId (b/17657656).
            }
        }

        // Query the SMS database for the threads
        Cursor cursor = getSmsCursorFromThreads(threadIdStrings);
        if (cursor != null) {
            try {
                List<ContactInteraction> interactions = new ArrayList<>();
                while (cursor.moveToNext()) {
                    ContentValues values = new ContentValues();
                    DatabaseUtils.cursorRowToContentValues(cursor, values);
                    interactions.add(new SmsInteraction(values));
                }

                return interactions;
            } finally {
                cursor.close();
            }
        }

        return Collections.emptyList();
    }

    /**
     * Return the most recent messages between a list of threads
     */
    private Cursor getSmsCursorFromThreads(List<String> threadIds) {
        if (threadIds.size() == 0) {
            return null;
        }
        String selection = Telephony.Sms.THREAD_ID + " IN "
                + ContactInteractionUtil.questionMarks(threadIds.size());

        return getContext().getContentResolver().query(
                Telephony.Sms.CONTENT_URI,
                /* projection = */ null,
                selection,
                threadIds.toArray(new String[threadIds.size()]),
                Telephony.Sms.DEFAULT_SORT_ORDER
                        + " LIMIT " + mMaxToRetrieve);
    }

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

        if (mData != null) {
            deliverResult(mData);
        }

        if (takeContentChanged() || mData == null) {
            forceLoad();
        }
    }

    @Override
    protected void onStopLoading() {
        // Attempt to cancel the current load task if possible.
        cancelLoad();
    }

    @Override
    public void deliverResult(List<ContactInteraction> data) {
        mData = data;
        if (isStarted()) {
            super.deliverResult(data);
        }
    }

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

        // Ensure the loader is stopped
        onStopLoading();
        if (mData != null) {
            mData.clear();
        }
    }
}
