package org.commcare.tasks;

import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.util.Pair;

import org.commcare.tasks.templates.CommCareTask;
import org.commcare.utils.GlobalConstants;
import org.commcare.utils.SigningUtil;
import org.joda.time.DateTime;

/**
 * Tries to find an install sms sent to the device of the format:
 *     [commcare app - do not delete] https://www.commcarehq.org/a/gc/sms/app_info/7c7d49fbef59b703fb468e20d52a21e4/
 *
 * If found:
 *  - Follows the http url to get app install info, which is base64-encoded
 *  - Base64 decodes that result into a string which looks like:
 *      ccapp: http://bit.ly/2cDCv0e signature: <binary signature>
 *  - Verifies the url is signed correctly using the signature and returns the
 *    url to be used to install the app
 */
public abstract class RetrieveParseVerifyMessageTask<R> extends CommCareTask<Void, Void, String, R> {

    /**
     * How many sms messages to scan over looking for commcare install link
     */
    private static final int SMS_CHECK_COUNT = 100;

    private Exception exception;
    private final RetrieveParseVerifyMessageListener listener;
    private final boolean installTriggeredManually;
    private final ContentResolver contentResolver;

    public RetrieveParseVerifyMessageTask(RetrieveParseVerifyMessageListener listener,
                                          ContentResolver contentResolver,
                                          boolean installTriggeredManually) {
        this.listener = listener;
        this.contentResolver = contentResolver;
        this.installTriggeredManually = installTriggeredManually;
    }

    @Override
    protected String doTaskBackground(Void... params) {
        // http://stackoverflow.com/questions/11301046/search-sms-inbox
        final Uri SMS_INBOX = Uri.parse("content://sms/inbox");

        DateTime oneDayAgo = (new DateTime()).minusDays(1);
        Cursor cursor = contentResolver.query(SMS_INBOX,
                null, "date >? ",
                new String[]{"" + oneDayAgo.getMillis()},
                "date DESC");

        int messageIterationCount = 0;
        if (cursor != null) {
            try {
                while (cursor.moveToNext() && messageIterationCount <= SMS_CHECK_COUNT) { // must check the result to prevent exception
                    messageIterationCount++;
                    String textMessageBody = cursor.getString(cursor.getColumnIndex("body"));
                    if (textMessageBody.contains(GlobalConstants.SMS_INSTALL_KEY_STRING)) {
                        return processSMS(textMessageBody);
                    }
                }
            } finally {
                cursor.close();
            }
        }
        return null;
    }

    private String processSMS(String smsText) {
        try {
            String url = SigningUtil.trimMessagePayload(smsText);
            String messagePayload = SigningUtil.convertEncodedUrlToPayload(url);
            byte[] messagePayloadBytes = SigningUtil.getBytesFromString(messagePayload);
            Pair<String, byte[]> messageAndBytes = SigningUtil.getUrlAndSignatureFromPayload(messagePayloadBytes);
            return SigningUtil.verifyMessageAndBytes(messageAndBytes.first, messageAndBytes.second);
        } catch (Exception e) {
            this.exception = e;
            return null;
        }
    }

    @Override
    protected void onPostExecute(String url) {
        super.onPostExecute(url);
        if (exception != null) {
            listener.exceptionReceived(exception, installTriggeredManually);
        }
        if (installTriggeredManually) {
            listener.downloadLinkReceivedAutoInstall(url);
        } else {
            listener.downloadLinkReceived(url);
        }
    }
}

@@ -1949,17 +1949,17 @@
 nusDays(
-1
+7
 );%0A     

change search range from 1 day in past to 7