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

import android.content.ContentResolver;
import android.net.Uri;
import android.os.Process;
import android.provider.DocumentsContract;
import android.util.Log;

import java.io.FileNotFoundException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

final class RootScanner {
    /**
     * Polling interval in milliseconds used for first SHORT_POLLING_TIMES because it is more
     * likely to add new root just after the device is added.
     */
    private final static long SHORT_POLLING_INTERVAL = 2000;

    /**
     * Polling interval in milliseconds for low priority polling, when changes are not expected.
     */
    private final static long LONG_POLLING_INTERVAL = 30 * 1000;

    /**
     * @see #SHORT_POLLING_INTERVAL
     */
    private final static long SHORT_POLLING_TIMES = 10;

    /**
     * Milliseconds we wait for background thread when pausing.
     */
    private final static long AWAIT_TERMINATION_TIMEOUT = 2000;

    final ContentResolver mResolver;
    final MtpManager mManager;
    final MtpDatabase mDatabase;

    ExecutorService mExecutor;
    private UpdateRootsRunnable mCurrentTask;

    RootScanner(
            ContentResolver resolver,
            MtpManager manager,
            MtpDatabase database) {
        mResolver = resolver;
        mManager = manager;
        mDatabase = database;
    }

    /**
     * Notifies a change of the roots list via ContentResolver.
     */
    void notifyChange() {
        final Uri uri = DocumentsContract.buildRootsUri(MtpDocumentsProvider.AUTHORITY);
        mResolver.notifyChange(uri, null, false);
    }

    /**
     * Starts to check new changes right away.
     */
    synchronized CountDownLatch resume() {
        if (mExecutor == null) {
            // Only single thread updates the database.
            mExecutor = Executors.newSingleThreadExecutor();
        }
        if (mCurrentTask != null) {
            // Stop previous task.
            mCurrentTask.stop();
        }
        mCurrentTask = new UpdateRootsRunnable();
        mExecutor.execute(mCurrentTask);
        return mCurrentTask.mFirstScanCompleted;
    }

    /**
     * Stops background thread and wait for its termination.
     * @throws InterruptedException
     */
    synchronized void pause() throws InterruptedException, TimeoutException {
        if (mExecutor == null) {
            return;
        }
        mExecutor.shutdownNow();
        try {
            if (!mExecutor.awaitTermination(AWAIT_TERMINATION_TIMEOUT, TimeUnit.MILLISECONDS)) {
                throw new TimeoutException(
                        "Timeout for terminating RootScanner's background thread.");
            }
        } finally {
            mExecutor = null;
        }
    }

    /**
     * Runnable to scan roots and update the database information.
     */
    private final class UpdateRootsRunnable implements Runnable {
        /**
         * Count down latch that specifies the runnable is stopped.
         */
        final CountDownLatch mStopped = new CountDownLatch(1);

        /**
         * Count down latch that specifies the first scan is completed.
         */
        final CountDownLatch mFirstScanCompleted = new CountDownLatch(1);

        @Override
        public void run() {
            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
            int pollingCount = 0;
            while (mStopped.getCount() > 0) {
                boolean changed = false;

                // Update devices.
                final MtpDeviceRecord[] devices = mManager.getDevices();
                try {
                    mDatabase.getMapper().startAddingDocuments(null /* parentDocumentId */);
                    for (final MtpDeviceRecord device : devices) {
                        if (mDatabase.getMapper().putDeviceDocument(device)) {
                            changed = true;
                        }
                    }
                    if (mDatabase.getMapper().stopAddingDocuments(
                            null /* parentDocumentId */)) {
                        changed = true;
                    }
                } catch (FileNotFoundException exception) {
                    // The top root (ID is null) must exist always.
                    // FileNotFoundException is unexpected.
                    Log.e(MtpDocumentsProvider.TAG, "Unexpected FileNotFoundException", exception);
                    throw new AssertionError("Unexpected exception for the top parent", exception);
                }

                // Update roots.
                for (final MtpDeviceRecord device : devices) {
                    final String documentId = mDatabase.getDocumentIdForDevice(device.deviceId);
                    if (documentId == null) {
                        continue;
                    }
                    try {
                        mDatabase.getMapper().startAddingDocuments(documentId);
                        if (mDatabase.getMapper().putStorageDocuments(
                                documentId, device.operationsSupported, device.roots)) {
                            changed = true;
                        }
                        if (mDatabase.getMapper().stopAddingDocuments(documentId)) {
                            changed = true;
                        }
                    } catch (FileNotFoundException exception) {
                        Log.e(MtpDocumentsProvider.TAG, "Parent document is gone.", exception);
                        continue;
                    }
                }

                if (changed) {
                    notifyChange();
                }
                mFirstScanCompleted.countDown();
                pollingCount++;
                if (devices.length == 0) {
                    break;
                }
                try {
                    // Use SHORT_POLLING_PERIOD for the first SHORT_POLLING_TIMES because it is
                    // more likely to add new root just after the device is added.
                    // TODO: Use short interval only for a device that is just added.
                    mStopped.await(pollingCount > SHORT_POLLING_TIMES ?
                            LONG_POLLING_INTERVAL : SHORT_POLLING_INTERVAL, TimeUnit.MILLISECONDS);
                } catch (InterruptedException exp) {
                    break;
                }
            }
        }

        void stop() {
            mStopped.countDown();
        }
    }
}
