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

import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.pm.ProviderInfo;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Parcelable;
import android.os.RemoteException;
import android.provider.DocumentsContract;
import android.test.MoreAsserts;
import android.test.ServiceTestCase;
import android.test.mock.MockContentResolver;
import android.util.Log;

import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.DocumentStack;
import com.android.documentsui.model.RootInfo;
import com.google.common.collect.Lists;

import libcore.io.IoUtils;
import libcore.io.Streams;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CopyTest extends ServiceTestCase<CopyService> {

    /**
     * A test resolver that enables this test suite to listen for notifications that mark when copy
     * operations are done.
     */
    class TestContentResolver extends MockContentResolver {
        private CountDownLatch mReadySignal;
        private CountDownLatch mNotificationSignal;

        public TestContentResolver() {
            mReadySignal = new CountDownLatch(1);
        }

        /**
         * Wait for the given number of files to be copied to destination. Times out after 1 sec.
         */
        public void waitForChanges(int count) throws Exception {
            // Wait for no more than 1 second by default.
            waitForChanges(count, 1000);
        }

        /**
         * Wait for files to be copied to destination.
         *
         * @param count Number of files to wait for.
         * @param timeOut Timeout in ms. TimeoutException will be thrown if this function times out.
         */
        public void waitForChanges(int count, int timeOut) throws Exception {
            mNotificationSignal = new CountDownLatch(count);
            // Signal that the test is now waiting for files.
            mReadySignal.countDown();
            if (!mNotificationSignal.await(timeOut, TimeUnit.MILLISECONDS)) {
                throw new TimeoutException("Timed out waiting for file operations to complete.");
            }
        }

        @Override
        public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
            // Wait until the test is ready to receive file notifications.
            try {
                mReadySignal.await();
            } catch (InterruptedException e) {
                Log.d(TAG, "Interrupted while waiting for file copy readiness");
                Thread.currentThread().interrupt();
            }
            if (DocumentsContract.isDocumentUri(mContext, uri)) {
                Log.d(TAG, "Notification: " + uri);
                // Watch for document URI change notifications - this signifies the end of a copy.
                mNotificationSignal.countDown();
            }
        }
    };

    public CopyTest() {
        super(CopyService.class);
    }

    private static String AUTHORITY = "com.android.documentsui.stubprovider";
    private static String DST = "sd1";
    private static String SRC = "sd0";
    private static String TAG = "CopyTest";
    private List<RootInfo> mRoots;
    private Context mContext;
    private TestContentResolver mResolver;
    private ContentProviderClient mClient;
    private StubProvider mStorage;
    private Context mSystemContext;

    @Override
    protected void setUp() throws Exception {
        super.setUp();

        setupTestContext();
        mClient = mResolver.acquireContentProviderClient(AUTHORITY);

        // Reset the stub provider's storage.
        mStorage.clearCacheAndBuildRoots();

        mRoots = Lists.newArrayList();
        Uri queryUri = DocumentsContract.buildRootsUri(AUTHORITY);
        Cursor cursor = null;
        try {
            cursor = mClient.query(queryUri, null, null, null, null);
            while (cursor.moveToNext()) {
                mRoots.add(RootInfo.fromRootsCursor(AUTHORITY, cursor));
            }
        } finally {
            IoUtils.closeQuietly(cursor);
        }

    }

    @Override
    protected void tearDown() throws Exception {
        mClient.release();
        super.tearDown();
    }

    /**
     * Test copying a single file.
     */
    public void testCopyFile() throws Exception {
        String srcPath = "/test0.txt";
        Uri testFile = mStorage.createFile(SRC, srcPath, "text/plain",
                "The five boxing wizards jump quickly".getBytes());

        assertDstFileCountEquals(0);

        startService(createCopyIntent(Lists.newArrayList(testFile)));

        // 2 operations: file creation, then writing data.
        mResolver.waitForChanges(2);

        // Verify that one file was copied; check file contents.
        assertDstFileCountEquals(1);
        assertCopied(srcPath);
    }

    public void testMoveFile() throws Exception {
        String srcPath = "/test0.txt";
        String testContent = "The five boxing wizards jump quickly";
        Uri testFile = mStorage.createFile(SRC, srcPath, "text/plain", testContent.getBytes());

        assertDstFileCountEquals(0);

        Intent moveIntent = createCopyIntent(Lists.newArrayList(testFile));
        moveIntent.putExtra(CopyService.EXTRA_TRANSFER_MODE, CopyService.TRANSFER_MODE_MOVE);
        startService(moveIntent);

        // 3 operations: file creation, writing data, deleting original.
        mResolver.waitForChanges(3);

        // Verify that one file was moved; check file contents.
        assertDstFileCountEquals(1);
        assertDoesNotExist(SRC, srcPath);

        byte[] dstContent = readFile(DST, srcPath);
        MoreAsserts.assertEquals("Moved file contents differ", testContent.getBytes(), dstContent);
    }

    /**
     * Test copying multiple files.
     */
    public void testCopyMultipleFiles() throws Exception {
        String testContent[] = {
                "The five boxing wizards jump quickly",
                "The quick brown fox jumps over the lazy dog",
                "Jackdaws love my big sphinx of quartz"
        };
        String srcPaths[] = {
                "/test0.txt",
                "/test1.txt",
                "/test2.txt"
        };
        List<Uri> testFiles = Lists.newArrayList(
                mStorage.createFile(SRC, srcPaths[0], "text/plain", testContent[0].getBytes()),
                mStorage.createFile(SRC, srcPaths[1], "text/plain", testContent[1].getBytes()),
                mStorage.createFile(SRC, srcPaths[2], "text/plain", testContent[2].getBytes()));

        assertDstFileCountEquals(0);

        // Copy all the test files.
        startService(createCopyIntent(testFiles));

        // 3 file creations, 3 file writes.
        mResolver.waitForChanges(6);

        assertDstFileCountEquals(3);
        for (String path : srcPaths) {
            assertCopied(path);
        }
    }

    public void testCopyEmptyDir() throws Exception {
        String srcPath = "/emptyDir";
        Uri testDir = mStorage.createFile(SRC, srcPath, DocumentsContract.Document.MIME_TYPE_DIR,
                null);

        assertDstFileCountEquals(0);

        startService(createCopyIntent(Lists.newArrayList(testDir)));

        // Just 1 operation: Directory creation.
        mResolver.waitForChanges(1);

        assertDstFileCountEquals(1);

        // Verify that the dst exists and is a directory.
        File dst = mStorage.getFile(DST, srcPath);
        assertTrue(dst.isDirectory());
    }

    public void testMoveEmptyDir() throws Exception {
        String srcPath = "/emptyDir";
        Uri testDir = mStorage.createFile(SRC, srcPath, DocumentsContract.Document.MIME_TYPE_DIR,
                null);

        assertDstFileCountEquals(0);

        Intent moveIntent = createCopyIntent(Lists.newArrayList(testDir));
        moveIntent.putExtra(CopyService.EXTRA_TRANSFER_MODE, CopyService.TRANSFER_MODE_MOVE);
        startService(moveIntent);

        // 2 operations: Directory creation, and removal of the original.
        mResolver.waitForChanges(2);

        assertDstFileCountEquals(1);

        // Verify that the dst exists and is a directory.
        File dst = mStorage.getFile(DST, srcPath);
        assertTrue(dst.isDirectory());

        // Verify that the src was cleaned up.
        assertDoesNotExist(SRC, srcPath);
    }

    public void testMovePopulatedDir() throws Exception {
        String testContent[] = {
                "The five boxing wizards jump quickly",
                "The quick brown fox jumps over the lazy dog",
                "Jackdaws love my big sphinx of quartz"
        };
        String srcDir = "/testdir";
        String srcFiles[] = {
                srcDir + "/test0.txt",
                srcDir + "/test1.txt",
                srcDir + "/test2.txt"
        };
        // Create test dir; put some files in it.
        Uri testDir = mStorage.createFile(SRC, srcDir, DocumentsContract.Document.MIME_TYPE_DIR,
                null);
        mStorage.createFile(SRC, srcFiles[0], "text/plain", testContent[0].getBytes());
        mStorage.createFile(SRC, srcFiles[1], "text/plain", testContent[1].getBytes());
        mStorage.createFile(SRC, srcFiles[2], "text/plain", testContent[2].getBytes());

        Intent moveIntent = createCopyIntent(Lists.newArrayList(testDir));
        moveIntent.putExtra(CopyService.EXTRA_TRANSFER_MODE, CopyService.TRANSFER_MODE_MOVE);
        startService(moveIntent);

        // dir creation, then creation and writing of 3 files, then removal of src dir and 3 src
        // files.
        mResolver.waitForChanges(11);

        // Check the content of the moved files.
        File dst = mStorage.getFile(DST, srcDir);
        assertTrue(dst.isDirectory());
        for (int i = 0; i < testContent.length; ++i) {
            byte[] dstContent = readFile(DST, srcFiles[i]);
            MoreAsserts.assertEquals("Copied file contents differ", testContent[i].getBytes(),
                    dstContent);
        }

        // Check that the src files were removed.
        assertDoesNotExist(SRC, srcDir);
        for (String srcFile : srcFiles) {
            assertDoesNotExist(SRC, srcFile);
        }
    }

    public void testCopyFileWithReadErrors() throws Exception {
        String srcPath = "/test0.txt";
        Uri testFile = mStorage.createFile(SRC, srcPath, "text/plain",
                "The five boxing wizards jump quickly".getBytes());

        assertDstFileCountEquals(0);

        mStorage.simulateReadErrorsForFile(testFile);

        startService(createCopyIntent(Lists.newArrayList(testFile)));

        // 3 operations: file creation, writing, then deletion (due to failed copy).
        mResolver.waitForChanges(3);

        // Verify that the failed copy was cleaned up.
        assertDstFileCountEquals(0);
    }

    public void testMoveFileWithReadErrors() throws Exception {
        String srcPath = "/test0.txt";
        Uri testFile = mStorage.createFile(SRC, srcPath, "text/plain",
                "The five boxing wizards jump quickly".getBytes());

        assertDstFileCountEquals(0);

        mStorage.simulateReadErrorsForFile(testFile);

        Intent moveIntent = createCopyIntent(Lists.newArrayList(testFile));
        moveIntent.putExtra(CopyService.EXTRA_TRANSFER_MODE, CopyService.TRANSFER_MODE_MOVE);
        startService(moveIntent);

        try {
            // There should be 3 operations: file creation, writing, then deletion (due to failed
            // copy). Wait for 4, in case the CopyService also attempts to do extra stuff (like
            // delete the src file). This should time out.
            mResolver.waitForChanges(4);
        } catch (TimeoutException e) {
            // Success path
            return;
        } finally {
            // Verify that the failed copy was cleaned up, and the src file wasn't removed.
            assertDstFileCountEquals(0);
            assertExists(SRC, srcPath);
        }
        // The asserts above didn't fail, but the CopyService did something unexpected.
        fail("Extra file operations were detected");
    }

    public void testMoveDirectoryWithReadErrors() throws Exception {
        String testContent[] = {
                "The five boxing wizards jump quickly",
                "The quick brown fox jumps over the lazy dog",
                "Jackdaws love my big sphinx of quartz"
        };
        String srcDir = "/testdir";
        String srcFiles[] = {
                srcDir + "/test0.txt",
                srcDir + "/test1.txt",
                srcDir + "/test2.txt"
        };
        // Create test dir; put some files in it.
        Uri testDir = mStorage.createFile(SRC, srcDir, DocumentsContract.Document.MIME_TYPE_DIR,
                null);
        mStorage.createFile(SRC, srcFiles[0], "text/plain", testContent[0].getBytes());
        Uri errFile = mStorage
                .createFile(SRC, srcFiles[1], "text/plain", testContent[1].getBytes());
        mStorage.createFile(SRC, srcFiles[2], "text/plain", testContent[2].getBytes());

        mStorage.simulateReadErrorsForFile(errFile);

        Intent moveIntent = createCopyIntent(Lists.newArrayList(testDir));
        moveIntent.putExtra(CopyService.EXTRA_TRANSFER_MODE, CopyService.TRANSFER_MODE_MOVE);
        startService(moveIntent);

        // - dst dir creation,
        // - creation and writing of 2 files, removal of 2 src files
        // - creation and writing of 1 file, then removal of that file (due to error)
        mResolver.waitForChanges(10);

        // Check that both the src and dst dirs exist. The src dir shouldn't have been removed,
        // because it should contain the one errFile.
        assertTrue(mStorage.getFile(SRC, srcDir).isDirectory());
        assertTrue(mStorage.getFile(DST, srcDir).isDirectory());

        // Check the content of the moved files.
        MoreAsserts.assertEquals("Copied file contents differ", testContent[0].getBytes(),
                readFile(DST, srcFiles[0]));
        MoreAsserts.assertEquals("Copied file contents differ", testContent[2].getBytes(),
                readFile(DST, srcFiles[2]));

        // Check that the src files were removed.
        assertDoesNotExist(SRC, srcFiles[0]);
        assertDoesNotExist(SRC, srcFiles[2]);

        // Check that the error file was not copied over.
        assertDoesNotExist(DST, srcFiles[1]);
        assertExists(SRC, srcFiles[1]);
    }

    /**
     * Copies the given files to a pre-determined destination.
     *
     * @throws FileNotFoundException
     */
    private Intent createCopyIntent(List<Uri> srcs) throws FileNotFoundException {
        final ArrayList<DocumentInfo> srcDocs = Lists.newArrayList();
        for (Uri src : srcs) {
            srcDocs.add(DocumentInfo.fromUri(mResolver, src));
        }

        final Uri dst = DocumentsContract.buildDocumentUri(AUTHORITY, mRoots.get(1).documentId);
        DocumentStack stack = new DocumentStack();
        stack.push(DocumentInfo.fromUri(mResolver, dst));
        final Intent copyIntent = new Intent(mContext, CopyService.class);
        copyIntent.putParcelableArrayListExtra(CopyService.EXTRA_SRC_LIST, srcDocs);
        copyIntent.putExtra(CopyService.EXTRA_STACK, (Parcelable) stack);

        // startService(copyIntent);
        return copyIntent;
    }

    /**
     * Returns a count of the files in the given directory.
     */
    private void assertDstFileCountEquals(int expected) throws RemoteException {
        final Uri queryUri = DocumentsContract.buildChildDocumentsUri(AUTHORITY,
                mRoots.get(1).documentId);
        Cursor c = null;
        int count = 0;
        try {
            c = mClient.query(queryUri, null, null, null, null);
            count = c.getCount();
        } finally {
            IoUtils.closeQuietly(c);
        }
        assertEquals("Incorrect file count after copy", expected, count);
    }

    private void assertExists(String rootId, String path) throws Exception {
        assertNotNull("An expected file was not found: " + path + " on root " + rootId,
                mStorage.getFile(rootId, path));
    }

    private void assertDoesNotExist(String rootId, String path) throws Exception {
        assertNull("Unexpected file found: " + path + " on root " + rootId,
                mStorage.getFile(rootId, path));
    }

    private byte[] readFile(String rootId, String path) throws Exception {
        File file = mStorage.getFile(rootId, path);
        byte[] buf = null;
        assertNotNull(file);

        FileInputStream in = null;
        try {
            in = new FileInputStream(file);
            buf = Streams.readFully(in);
        } finally {
            IoUtils.closeQuietly(in);
        }
        return buf;
    }

    private void assertCopied(String path) throws Exception {
        MoreAsserts.assertEquals("Copied file contents differ", readFile(SRC, path),
                readFile(DST, path));
    }

    /**
     * Sets up a ContextWrapper that substitutes a stub NotificationManager. This allows the test to
     * listen for notification events, to gauge copy progress.
     *
     * @throws FileNotFoundException
     */
    private void setupTestContext() throws FileNotFoundException {
        mSystemContext = getSystemContext();

        // Set up the context with the test content resolver.
        mResolver = new TestContentResolver();
        mContext = new ContextWrapper(mSystemContext) {
            @Override
            public ContentResolver getContentResolver() {
                return mResolver;
            }
        };
        setContext(mContext);

        // Create a local stub provider and add it to the content resolver.
        ProviderInfo info = new ProviderInfo();
        info.authority = AUTHORITY;
        info.exported = true;
        info.grantUriPermissions = true;
        info.readPermission = android.Manifest.permission.MANAGE_DOCUMENTS;
        info.writePermission = android.Manifest.permission.MANAGE_DOCUMENTS;

        mStorage = new StubProvider();
        mStorage.attachInfo(mContext, info);
        mResolver.addProvider(AUTHORITY, mStorage);
    }
}
