/*
 * Copyright (C) 2017 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 android.provider.cts.contactsproviderwipe;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.platform.test.annotations.AppModeFull;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Intents;
import android.provider.ContactsContract.ProviderStatus;
import android.support.test.InstrumentationRegistry;
import android.test.AndroidTestCase;
import android.text.TextUtils;
import android.util.Log;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
 * CTS tests for CP2 regarding data wipe.
 *
 * <p>We can't use CtsProviderTestCases for this test because CtsProviderTestCases creates
 * a stable connection to the contacts provider, which would cause the test process to be killed
 * when the CP2 process gets killed (for "pm clear").
 */
@AppModeFull // Requires READ/WRITE_CONTACTS.
public class ContactsContract_Wipe extends AndroidTestCase {
    public static final String TAG = "ContactsContract_PS";

    /** 1 hour in milliseconds. */
    private static final long ONE_HOUR_IN_MILLIS = 1000L * 60 * 60;

    private long getDatabaseCreationTimestamp() {
        try (Cursor cursor = getContext().getContentResolver().query(
                ProviderStatus.CONTENT_URI, null, null, null, null)) {
            assertTrue(cursor.moveToFirst());

            final Long timestamp = cursor.getLong(
                    cursor.getColumnIndexOrThrow(ProviderStatus.DATABASE_CREATION_TIMESTAMP));
            assertNotNull(timestamp);

            return timestamp;
        }
    }

    private void assertBigger(long bigger, long smaller) {
        assertTrue("Expecting " + bigger + " > " + smaller, bigger > smaller);
    }

    private String getContactsProviderPackageName() {
        final List<ProviderInfo> list = getContext().getPackageManager().queryContentProviders(
                null, 0, PackageManager.MATCH_ALL);
        assertNotNull(list);
        for (ProviderInfo pi : list) {
            if (TextUtils.isEmpty(pi.authority)) {
                continue;
            }
            for (String authority : pi.authority.split(";")) {
                Log.i(TAG, "Found " + authority);
                if (ContactsContract.AUTHORITY.equals(authority)) {
                    return pi.packageName;
                }
            }
        }
        fail("Contacts provider package not found.");
        return null;
    }

    static List<String> readAll(ParcelFileDescriptor pfd) {
        try {
            try {
                final ArrayList<String> ret = new ArrayList<>();
                try (BufferedReader r = new BufferedReader(
                        new FileReader(pfd.getFileDescriptor()))) {
                    String line;
                    while ((line = r.readLine()) != null) {
                        ret.add(line);
                    }
                    r.readLine();
                }
                return ret;
            } finally {
                pfd.close();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    static String concatResult(List<String> result) {
        final StringBuilder sb = new StringBuilder();
        for (String s : result) {
            sb.append(s);
            sb.append("\n");
        }
        return sb.toString().trim();
    }

    private void wipeContactsProvider() {
        final String providerPackage = getContactsProviderPackageName();

        Log.i(TAG, "Wiping "  + providerPackage + "...");

        final String result = concatResult(readAll(
                InstrumentationRegistry.getInstrumentation().getUiAutomation().executeShellCommand(
                        "pm clear " + providerPackage)));
        Log.i(TAG, "Result:" + result);

        assertEquals("Success", result);
    }

    public void testCreationTimestamp() throws Exception {
        final long originalTimestamp = getDatabaseCreationTimestamp();

        Thread.sleep(1);

        final long start = System.currentTimeMillis();

        Log.i(TAG, "start="  + start);
        Log.i(TAG, "originalTimestamp="  + originalTimestamp);

        // Check: the (old) creation time should be smaller than the start time (=now).
        // Add 1 hour to compensate for possible day light saving.
        assertBigger(start + ONE_HOUR_IN_MILLIS, originalTimestamp);

        Thread.sleep(1);

        wipeContactsProvider();

        // Check: the creation time should be bigger than the start time.
        final long newTimestamp = getDatabaseCreationTimestamp();
        Log.i(TAG, "newTimestamp="  + newTimestamp);

        assertBigger(newTimestamp, start);
    }

    public void testDatabaseWipeNotification() throws Exception {
        final CountDownLatch latch = new CountDownLatch(1);
        final AtomicReference<Uri> notifiedUri = new AtomicReference<>();

        getContext().getContentResolver().registerContentObserver(ProviderStatus.CONTENT_URI,
                /* notifyForDescendants=*/ false,
                new ContentObserver(new Handler(Looper.getMainLooper())) {
            @Override
            public void onChange(boolean selfChange, Uri uri) {
                Log.i(TAG, "Received notification on " + uri);
                notifiedUri.set(uri);
                latch.countDown();
            }
        });

        wipeContactsProvider();

        // Accessing CP2 to make sure the process starts.
        getDatabaseCreationTimestamp();

        assertTrue("Didn't receive content change notification",
                latch.await(120, TimeUnit.SECONDS));

        assertEquals(ProviderStatus.CONTENT_URI, notifiedUri.get());
    }

    public void testDatabaseWipeBroadcast() throws Exception {
        final CountDownLatch latch = new CountDownLatch(1);

        final IntentFilter filter = new IntentFilter();
        filter.addAction(Intents.CONTACTS_DATABASE_CREATED);

        getContext().registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                Log.i(TAG, "Received broadcast: " + intent);
                latch.countDown();
            }
        }, filter);

        wipeContactsProvider();

        // Accessing CP2 to make sure the process starts.
        getDatabaseCreationTimestamp();

        assertTrue("Didn't receive contacts wipe broadcast",
                latch.await(120, TimeUnit.SECONDS));
    }
}
