/*
 * 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.common.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();
        }
    }
}
