/*
 * 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.tv.tuner.exoplayer2.buffer;

import android.content.Context;
import android.os.AsyncTask;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.util.Pair;
import com.android.tv.common.SoftPreconditions;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedMap;

/** Manages Trickplay storage. */
public class TrickplayStorageManager implements BufferManager.StorageManager {
    // TODO: Support multi-sessions.
    private static final String BUFFER_DIR = "timeshift";

    // Copied from android.provider.Settings.Global (hidden fields)
    private static final String SYS_STORAGE_THRESHOLD_PERCENTAGE =
            "sys_storage_threshold_percentage";
    private static final String SYS_STORAGE_THRESHOLD_MAX_BYTES = "sys_storage_threshold_max_bytes";

    // Copied from android.os.StorageManager
    private static final int DEFAULT_THRESHOLD_PERCENTAGE = 10;
    private static final long DEFAULT_THRESHOLD_MAX_BYTES = 500L * 1024 * 1024;

    private static AsyncTask<Void, Void, Void> sLastCacheCleanUpTask;
    private static File sBufferDir;
    private static long sStorageBufferBytes;

    private final long mMaxBufferSize;

    private static void initParamsIfNeeded(Context context, @NonNull File path) {
        // TODO: Support multi-sessions.
        SoftPreconditions.checkState(sBufferDir == null || sBufferDir.equals(path));
        if (path.equals(sBufferDir)) {
            return;
        }
        sBufferDir = path;
        long lowPercentage =
                Settings.Global.getInt(
                        context.getContentResolver(),
                        SYS_STORAGE_THRESHOLD_PERCENTAGE,
                        DEFAULT_THRESHOLD_PERCENTAGE);
        long lowPercentageToBytes = path.getTotalSpace() * lowPercentage / 100;
        long maxLowBytes =
                Settings.Global.getLong(
                        context.getContentResolver(),
                        SYS_STORAGE_THRESHOLD_MAX_BYTES,
                        DEFAULT_THRESHOLD_MAX_BYTES);
        sStorageBufferBytes = Math.min(lowPercentageToBytes, maxLowBytes);
    }

    public TrickplayStorageManager(Context context, @NonNull File baseDir, long maxBufferSize) {
        initParamsIfNeeded(context, new File(baseDir, BUFFER_DIR));
        sBufferDir.mkdirs();
        mMaxBufferSize = maxBufferSize;
        clearStorage();
    }

    private void clearStorage() {
        long now = System.currentTimeMillis();
        if (sLastCacheCleanUpTask != null) {
            sLastCacheCleanUpTask.cancel(true);
        }
        sLastCacheCleanUpTask =
                new AsyncTask<Void, Void, Void>() {
                    @Override
                    protected Void doInBackground(Void... params) {
                        if (isCancelled()) {
                            return null;
                        }
                        File files[] = sBufferDir.listFiles();
                        if (files == null || files.length == 0) {
                            return null;
                        }
                        for (File file : files) {
                            if (isCancelled()) {
                                break;
                            }
                            long lastModified = file.lastModified();
                            if (lastModified != 0 && lastModified < now) {
                                file.delete();
                            }
                        }
                        return null;
                    }
                };
        sLastCacheCleanUpTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }

    @Override
    public File getBufferDir() {
        return sBufferDir;
    }

    @Override
    public boolean isPersistent() {
        return false;
    }

    @Override
    public boolean reachedStorageMax(long bufferSize, long pendingDelete) {
        return bufferSize - pendingDelete > mMaxBufferSize;
    }

    @Override
    public boolean hasEnoughBuffer(long pendingDelete) {
        return sBufferDir.getUsableSpace() + pendingDelete >= sStorageBufferBytes;
    }

    @Override
    public List<BufferManager.TrackFormat> readTrackInfoFiles(boolean isAudio) {
        return null;
    }

    @Override
    public ArrayList<BufferManager.PositionHolder> readIndexFile(String trackId) {
        return null;
    }

    @Override
    public void writeTrackInfoFiles(List<BufferManager.TrackFormat> formatList, boolean isAudio) {}

    @Override
    public void writeIndexFile(
            String trackName, SortedMap<Long, Pair<SampleChunk, Integer>> index) {}

    @Override
    public void updateIndexFile(
            String trackName, int size, long position, SampleChunk sampleChunk, int offset) {}
}
