/*
 * 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.tv.dvr;

import android.content.BroadcastReceiver;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.media.tv.TvContract;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.Looper;
import android.os.RemoteException;
import android.os.StatFs;
import android.support.annotation.AnyThread;
import android.support.annotation.IntDef;
import android.support.annotation.WorkerThread;
import android.util.Log;

import com.android.tv.common.SoftPreconditions;
import com.android.tv.common.feature.CommonFeatures;
import com.android.tv.util.Utils;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * Signals DVR storage status change such as plugging/unplugging.
 */
public class DvrStorageStatusManager {
    private static final String TAG = "DvrStorageStatusManager";
    private static final boolean DEBUG = false;

    /**
     * Minimum storage size to support DVR
     */
    public static final long MIN_STORAGE_SIZE_FOR_DVR_IN_BYTES = 50 * 1024 * 1024 * 1024L; // 50GB
    private static final long MIN_FREE_STORAGE_SIZE_FOR_DVR_IN_BYTES
            = 10 * 1024 * 1024 * 1024L; // 10GB
    private static final String RECORDING_DATA_SUB_PATH = "/recording";

    private static final String[] PROJECTION = {
            TvContract.RecordedPrograms._ID,
            TvContract.RecordedPrograms.COLUMN_PACKAGE_NAME,
            TvContract.RecordedPrograms.COLUMN_RECORDING_DATA_URI
    };
    private final static int BATCH_OPERATION_COUNT = 100;

    @IntDef({STORAGE_STATUS_OK, STORAGE_STATUS_TOTAL_CAPACITY_TOO_SMALL,
            STORAGE_STATUS_FREE_SPACE_INSUFFICIENT, STORAGE_STATUS_MISSING})
    @Retention(RetentionPolicy.SOURCE)
    public @interface StorageStatus {
    }

    /**
     * Current storage is OK to record a program.
     */
    public static final int STORAGE_STATUS_OK = 0;

    /**
     * Current storage's total capacity is smaller than DVR requirement.
     */
    public static final int STORAGE_STATUS_TOTAL_CAPACITY_TOO_SMALL = 1;

    /**
     * Current storage's free space is insufficient to record programs.
     */
    public static final int STORAGE_STATUS_FREE_SPACE_INSUFFICIENT = 2;

    /**
     * Current storage is missing.
     */
    public static final int STORAGE_STATUS_MISSING = 3;

    private final Context mContext;
    private final Set<OnStorageMountChangedListener> mOnStorageMountChangedListeners =
            new CopyOnWriteArraySet<>();
    private final boolean mRunningInMainProcess;
    private MountedStorageStatus mMountedStorageStatus;
    private boolean mStorageValid;
    private CleanUpDbTask mCleanUpDbTask;

    private class MountedStorageStatus {
        private final boolean mStorageMounted;
        private final File mStorageMountedDir;
        private final long mStorageMountedCapacity;

        private MountedStorageStatus(boolean mounted, File mountedDir, long capacity) {
            mStorageMounted = mounted;
            mStorageMountedDir = mountedDir;
            mStorageMountedCapacity = capacity;
        }

        private boolean isValidForDvr() {
            return mStorageMounted && mStorageMountedCapacity >= MIN_STORAGE_SIZE_FOR_DVR_IN_BYTES;
        }

        @Override
        public boolean equals(Object other) {
            if (!(other instanceof MountedStorageStatus)) {
                return false;
            }
            MountedStorageStatus status = (MountedStorageStatus) other;
            return mStorageMounted == status.mStorageMounted
                    && Objects.equals(mStorageMountedDir, status.mStorageMountedDir)
                    && mStorageMountedCapacity == status.mStorageMountedCapacity;
        }
    }

    public interface OnStorageMountChangedListener {

        /**
         * Listener for DVR storage status change.
         *
         * @param storageMounted {@code true} when DVR possible storage is mounted,
         *                       {@code false} otherwise.
         */
        void onStorageMountChanged(boolean storageMounted);
    }

    private final class StorageStatusBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            MountedStorageStatus result = getStorageStatusInternal();
            if (mMountedStorageStatus.equals(result)) {
                return;
            }
            mMountedStorageStatus = result;
            if (result.mStorageMounted && mRunningInMainProcess) {
                // Cleans up DB in LC process.
                // Tuner process is not always on.
                if (mCleanUpDbTask != null) {
                    mCleanUpDbTask.cancel(true);
                }
                mCleanUpDbTask = new CleanUpDbTask();
                mCleanUpDbTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
            }
            boolean valid = result.isValidForDvr();
            if (valid == mStorageValid) {
                return;
            }
            mStorageValid = valid;
            for (OnStorageMountChangedListener l : mOnStorageMountChangedListeners) {
                l.onStorageMountChanged(valid);
            }
        }
    }

    /**
     * Creates DvrStorageStatusManager.
     *
     * @param context {@link Context}
     */
    public DvrStorageStatusManager(final Context context, boolean runningInMainProcess) {
        mContext = context;
        mRunningInMainProcess = runningInMainProcess;
        mMountedStorageStatus = getStorageStatusInternal();
        mStorageValid = mMountedStorageStatus.isValidForDvr();
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
        filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
        filter.addAction(Intent.ACTION_MEDIA_EJECT);
        filter.addAction(Intent.ACTION_MEDIA_REMOVED);
        filter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL);
        filter.addDataScheme(ContentResolver.SCHEME_FILE);
        mContext.registerReceiver(new StorageStatusBroadcastReceiver(), filter);
    }

    /**
     * Adds the listener for receiving storage status change.
     *
     * @param listener
     */
    public void addListener(OnStorageMountChangedListener listener) {
        mOnStorageMountChangedListeners.add(listener);
    }

    /**
     * Removes the current listener.
     */
    public void removeListener(OnStorageMountChangedListener listener) {
        mOnStorageMountChangedListeners.remove(listener);
    }

    /**
     * Returns true if a storage is mounted.
     */
    public boolean isStorageMounted() {
        return mMountedStorageStatus.mStorageMounted;
    }

    /**
     * Returns the path to DVR recording data directory.
     * This can take for a while sometimes.
     */
    @WorkerThread
    public File getRecordingRootDataDirectory() {
        SoftPreconditions.checkState(Looper.myLooper() != Looper.getMainLooper());
        if (mMountedStorageStatus.mStorageMountedDir == null) {
            return null;
        }
        File root = mContext.getExternalFilesDir(null);
        String rootPath;
        try {
            rootPath = root != null ? root.getCanonicalPath() : null;
        } catch (IOException | SecurityException e) {
            return null;
        }
        return rootPath == null ? null : new File(rootPath + RECORDING_DATA_SUB_PATH);
    }

    /**
     * Returns the current storage status for DVR recordings.
     *
     * @return {@link StorageStatus}
     */
    @AnyThread
    public @StorageStatus int getDvrStorageStatus() {
        MountedStorageStatus status = mMountedStorageStatus;
        if (status.mStorageMountedDir == null) {
            return STORAGE_STATUS_MISSING;
        }
        if (CommonFeatures.FORCE_RECORDING_UNTIL_NO_SPACE.isEnabled(mContext)) {
            return STORAGE_STATUS_OK;
        }
        if (status.mStorageMountedCapacity < MIN_STORAGE_SIZE_FOR_DVR_IN_BYTES) {
            return STORAGE_STATUS_TOTAL_CAPACITY_TOO_SMALL;
        }
        try {
            StatFs statFs = new StatFs(status.mStorageMountedDir.toString());
            if (statFs.getAvailableBytes() < MIN_FREE_STORAGE_SIZE_FOR_DVR_IN_BYTES) {
                return STORAGE_STATUS_FREE_SPACE_INSUFFICIENT;
            }
        } catch (IllegalArgumentException e) {
            // In rare cases, storage status change was not notified yet.
            SoftPreconditions.checkState(false);
            return STORAGE_STATUS_FREE_SPACE_INSUFFICIENT;
        }
        return STORAGE_STATUS_OK;
    }

    /**
     * Returns whether the storage has sufficient storage.
     *
     * @return {@code true} when there is sufficient storage, {@code false} otherwise
     */
    public boolean isStorageSufficient() {
        return getDvrStorageStatus() == STORAGE_STATUS_OK;
    }

    private MountedStorageStatus getStorageStatusInternal() {
        boolean storageMounted =
                Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
        File storageMountedDir = storageMounted ? Environment.getExternalStorageDirectory() : null;
        storageMounted = storageMounted && storageMountedDir != null;
        long storageMountedCapacity = 0L;
        if (storageMounted) {
            try {
                StatFs statFs = new StatFs(storageMountedDir.toString());
                storageMountedCapacity = statFs.getTotalBytes();
            } catch (IllegalArgumentException e) {
                Log.e(TAG, "Storage mount status was changed.");
                storageMounted = false;
                storageMountedDir = null;
            }
        }
        return new MountedStorageStatus(
                storageMounted, storageMountedDir, storageMountedCapacity);
    }

    private class CleanUpDbTask extends AsyncTask<Void, Void, Void> {
        private final ContentResolver mContentResolver;

        private CleanUpDbTask() {
            mContentResolver = mContext.getContentResolver();
        }

        @Override
        protected Void doInBackground(Void... params) {
            @DvrStorageStatusManager.StorageStatus int storageStatus = getDvrStorageStatus();
            if (storageStatus == DvrStorageStatusManager.STORAGE_STATUS_MISSING) {
                return null;
            }
            List<ContentProviderOperation> ops = getDeleteOps(storageStatus
                    == DvrStorageStatusManager.STORAGE_STATUS_TOTAL_CAPACITY_TOO_SMALL);
            if (ops == null || ops.isEmpty()) {
                return null;
            }
            Log.i(TAG, "New device storage mounted. # of recordings to be forgotten : "
                    + ops.size());
            for (int i = 0 ; i < ops.size() && !isCancelled() ; i += BATCH_OPERATION_COUNT) {
                int toIndex = (i + BATCH_OPERATION_COUNT) > ops.size()
                        ? ops.size() : (i + BATCH_OPERATION_COUNT);
                ArrayList<ContentProviderOperation> batchOps =
                        new ArrayList<>(ops.subList(i, toIndex));
                try {
                    mContext.getContentResolver().applyBatch(TvContract.AUTHORITY, batchOps);
                } catch (RemoteException | OperationApplicationException e) {
                    Log.e(TAG, "Failed to clean up  RecordedPrograms.", e);
                }
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            if (mCleanUpDbTask == this) {
                mCleanUpDbTask = null;
            }
        }

        private List<ContentProviderOperation> getDeleteOps(boolean deleteAll) {
            List<ContentProviderOperation> ops = new ArrayList<>();

            try (Cursor c = mContentResolver.query(
                    TvContract.RecordedPrograms.CONTENT_URI, PROJECTION, null, null, null)) {
                if (c == null) {
                    return null;
                }
                while (c.moveToNext()) {
                    @DvrStorageStatusManager.StorageStatus int storageStatus =
                            getDvrStorageStatus();
                    if (isCancelled()
                            || storageStatus == DvrStorageStatusManager.STORAGE_STATUS_MISSING) {
                        ops.clear();
                        break;
                    }
                    String id = c.getString(0);
                    String packageName = c.getString(1);
                    String dataUriString = c.getString(2);
                    if (dataUriString == null) {
                        continue;
                    }
                    Uri dataUri = Uri.parse(dataUriString);
                    if (!Utils.isInBundledPackageSet(packageName)
                            || dataUri == null || dataUri.getPath() == null
                            || !ContentResolver.SCHEME_FILE.equals(dataUri.getScheme())) {
                        continue;
                    }
                    File recordedProgramDir = new File(dataUri.getPath());
                    if (deleteAll || !recordedProgramDir.exists()) {
                        ops.add(ContentProviderOperation.newDelete(
                                TvContract.buildRecordedProgramUri(Long.parseLong(id))).build());
                    }
                }
                return ops;
            }
        }
    }
}
