/*
 * Copyright (C) 2011 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.settings.deviceinfo;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.PackageManager;
import android.content.pm.PackageStats;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.storage.StorageVolume;
import android.util.Log;

import com.android.internal.app.IMediaContainerService;

import java.io.File;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Measure the memory for various systems.
 *
 * TODO: This class should ideally have less knowledge about what the context
 * it's measuring is. In the future, reduce the amount of stuff it needs to
 * know about by just keeping an array of measurement types of the following
 * properties:
 *
 *   Filesystem stats (using DefaultContainerService)
 *   Directory measurements (using DefaultContainerService.measureDir)
 *   Application measurements (using PackageManager)
 *
 * Then the calling application would just specify the type and an argument.
 * This class would keep track of it while the calling application would
 * decide on how to use it.
 */
public class StorageMeasurement {
    private static final String TAG = "StorageMeasurement";

    private static final boolean LOCAL_LOGV = true;
    static final boolean LOGV = LOCAL_LOGV && Log.isLoggable(TAG, Log.VERBOSE);

    public static final String TOTAL_SIZE = "total_size";

    public static final String AVAIL_SIZE = "avail_size";

    public static final String APPS_USED = "apps_used";

    public static final String DOWNLOADS_SIZE = "downloads_size";

    public static final String MISC_SIZE = "misc_size";

    public static final String MEDIA_SIZES = "media_sizes";

    private static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";

    public static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
            DEFAULT_CONTAINER_PACKAGE, "com.android.defcontainer.DefaultContainerService");

    private final MeasurementHandler mHandler;

    private static Map<StorageVolume, StorageMeasurement> sInstances =
        new ConcurrentHashMap<StorageVolume, StorageMeasurement>();
    private static StorageMeasurement sInternalInstance;

    private volatile WeakReference<MeasurementReceiver> mReceiver;

    private long mTotalSize;
    private long mAvailSize;
    private long mAppsSize;
    private long mDownloadsSize;
    private long mMiscSize;
    private long[] mMediaSizes = new long[StorageVolumePreferenceCategory.sMediaCategories.length];

    final private StorageVolume mStorageVolume;
    final private boolean mIsPrimary;
    final private boolean mIsInternal;

    List<FileInfo> mFileInfoForMisc;

    public interface MeasurementReceiver {
        public void updateApproximate(Bundle bundle);
        public void updateExact(Bundle bundle);
    }

    private StorageMeasurement(Context context, StorageVolume storageVolume, boolean isPrimary) {
        mStorageVolume = storageVolume;
        mIsInternal = storageVolume == null;
        mIsPrimary = !mIsInternal && isPrimary;

        // Start the thread that will measure the disk usage.
        final HandlerThread handlerThread = new HandlerThread("MemoryMeasurement");
        handlerThread.start();
        mHandler = new MeasurementHandler(context, handlerThread.getLooper());
    }

    /**
     * Get the singleton of the StorageMeasurement class. The application
     * context is used to avoid leaking activities.
     * @param storageVolume The {@link StorageVolume} that will be measured
     * @param isPrimary true when this storage volume is the primary volume
     */
    public static StorageMeasurement getInstance(Context context, StorageVolume storageVolume,
            boolean isPrimary) {
        if (storageVolume == null) {
            if (sInternalInstance == null) {
                sInternalInstance =
                    new StorageMeasurement(context.getApplicationContext(), storageVolume, isPrimary);
            }
            return sInternalInstance;
        }
        if (sInstances.containsKey(storageVolume)) {
            return sInstances.get(storageVolume);
        } else {
            StorageMeasurement storageMeasurement =
                new StorageMeasurement(context.getApplicationContext(), storageVolume, isPrimary);
            sInstances.put(storageVolume, storageMeasurement);
            return storageMeasurement;
        }
    }

    public void setReceiver(MeasurementReceiver receiver) {
        if (mReceiver == null || mReceiver.get() == null) {
            mReceiver = new WeakReference<MeasurementReceiver>(receiver);
        }
    }

    public void measure() {
        if (!mHandler.hasMessages(MeasurementHandler.MSG_MEASURE)) {
            mHandler.sendEmptyMessage(MeasurementHandler.MSG_MEASURE);
        }
    }

    public void cleanUp() {
        mReceiver = null;
        mHandler.removeMessages(MeasurementHandler.MSG_MEASURE);
        mHandler.sendEmptyMessage(MeasurementHandler.MSG_DISCONNECT);
    }

    public void invalidate() {
        mHandler.sendEmptyMessage(MeasurementHandler.MSG_INVALIDATE);
    }

    private void sendInternalApproximateUpdate() {
        MeasurementReceiver receiver = (mReceiver != null) ? mReceiver.get() : null;
        if (receiver == null) {
            return;
        }

        Bundle bundle = new Bundle();
        bundle.putLong(TOTAL_SIZE, mTotalSize);
        bundle.putLong(AVAIL_SIZE, mAvailSize);

        receiver.updateApproximate(bundle);
    }

    private void sendExactUpdate() {
        MeasurementReceiver receiver = (mReceiver != null) ? mReceiver.get() : null;
        if (receiver == null) {
            if (LOGV) {
                Log.i(TAG, "measurements dropped because receiver is null! wasted effort");
            }
            return;
        }

        Bundle bundle = new Bundle();
        bundle.putLong(TOTAL_SIZE, mTotalSize);
        bundle.putLong(AVAIL_SIZE, mAvailSize);
        bundle.putLong(APPS_USED, mAppsSize);
        bundle.putLong(DOWNLOADS_SIZE, mDownloadsSize);
        bundle.putLong(MISC_SIZE, mMiscSize);
        bundle.putLongArray(MEDIA_SIZES, mMediaSizes);

        receiver.updateExact(bundle);
    }

    private class MeasurementHandler extends Handler {
        public static final int MSG_MEASURE = 1;

        public static final int MSG_CONNECTED = 2;

        public static final int MSG_DISCONNECT = 3;

        public static final int MSG_COMPLETED = 4;

        public static final int MSG_INVALIDATE = 5;

        private Object mLock = new Object();

        private IMediaContainerService mDefaultContainer;

        private volatile boolean mBound = false;

        private volatile boolean mMeasured = false;

        private StatsObserver mStatsObserver;

        private final WeakReference<Context> mContext;

        final private ServiceConnection mDefContainerConn = new ServiceConnection() {
            public void onServiceConnected(ComponentName name, IBinder service) {
                final IMediaContainerService imcs = IMediaContainerService.Stub
                .asInterface(service);
                mDefaultContainer = imcs;
                mBound = true;
                sendMessage(obtainMessage(MSG_CONNECTED, imcs));
            }

            public void onServiceDisconnected(ComponentName name) {
                mBound = false;
                removeMessages(MSG_CONNECTED);
            }
        };

        public MeasurementHandler(Context context, Looper looper) {
            super(looper);
            mContext = new WeakReference<Context>(context);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_MEASURE: {
                    if (mMeasured) {
                        sendExactUpdate();
                        break;
                    }

                    final Context context = (mContext != null) ? mContext.get() : null;
                    if (context == null) {
                        return;
                    }

                    synchronized (mLock) {
                        if (mBound) {
                            removeMessages(MSG_DISCONNECT);
                            sendMessage(obtainMessage(MSG_CONNECTED, mDefaultContainer));
                        } else {
                            Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
                            context.bindService(service, mDefContainerConn,
                                    Context.BIND_AUTO_CREATE);
                        }
                    }
                    break;
                }
                case MSG_CONNECTED: {
                    IMediaContainerService imcs = (IMediaContainerService) msg.obj;
                    measureApproximateStorage(imcs);
                    measureExactStorage(imcs);
                    break;
                }
                case MSG_DISCONNECT: {
                    synchronized (mLock) {
                        if (mBound) {
                            final Context context = (mContext != null) ? mContext.get() : null;
                            if (context == null) {
                                return;
                            }

                            mBound = false;
                            context.unbindService(mDefContainerConn);
                        }
                    }
                    break;
                }
                case MSG_COMPLETED: {
                    mMeasured = true;
                    sendExactUpdate();
                    break;
                }
                case MSG_INVALIDATE: {
                    mMeasured = false;
                    break;
                }
            }
        }

        /**
         * Request measurement of each package.
         *
         * @param pm PackageManager instance to query
         */
        public void requestQueuedMeasurementsLocked(PackageManager pm) {
            final String[] appsList = mStatsObserver.getAppsList();
            final int N = appsList.length;
            for (int i = 0; i < N; i++) {
                pm.getPackageSizeInfo(appsList[i], mStatsObserver);
            }
        }

        private class StatsObserver extends IPackageStatsObserver.Stub {
            private long mAppsSizeForThisStatsObserver = 0;
            private final List<String> mAppsList = new ArrayList<String>();

            public void onGetStatsCompleted(PackageStats stats, boolean succeeded) {
                if (!mStatsObserver.equals(this)) {
                    // this callback's class object is no longer in use. ignore this callback.
                    return;
                }

                if (succeeded) {
                    if (mIsInternal) {
                        mAppsSizeForThisStatsObserver += stats.codeSize + stats.dataSize;
                    } else if (!Environment.isExternalStorageEmulated()) {
                        mAppsSizeForThisStatsObserver += stats.externalObbSize +
                                stats.externalCodeSize + stats.externalDataSize +
                                stats.externalCacheSize + stats.externalMediaSize;
                    } else {
                        mAppsSizeForThisStatsObserver += stats.codeSize + stats.dataSize +
                                stats.externalCodeSize + stats.externalDataSize +
                                stats.externalCacheSize + stats.externalMediaSize +
                                stats.externalObbSize;
                    }
                }

                synchronized (mAppsList) {
                    mAppsList.remove(stats.packageName);
                    if (mAppsList.size() > 0) return;
                }

                mAppsSize = mAppsSizeForThisStatsObserver;
                onInternalMeasurementComplete();
            }

            public void queuePackageMeasurementLocked(String packageName) {
                synchronized (mAppsList) {
                    mAppsList.add(packageName);
                }
            }

            public String[] getAppsList() {
                synchronized (mAppsList) {
                    return mAppsList.toArray(new String[mAppsList.size()]);
                }
            }
        }

        private void onInternalMeasurementComplete() {
            sendEmptyMessage(MSG_COMPLETED);
        }

        private void measureApproximateStorage(IMediaContainerService imcs) {
            final String path = mStorageVolume != null ? mStorageVolume.getPath()
                    : Environment.getDataDirectory().getPath();
            try {
                final long[] stats = imcs.getFileSystemStats(path);
                mTotalSize = stats[0];
                mAvailSize = stats[1];
            } catch (RemoteException e) {
                Log.w(TAG, "Problem in container service", e);
            }

            sendInternalApproximateUpdate();
        }

        private void measureExactStorage(IMediaContainerService imcs) {
            Context context = mContext != null ? mContext.get() : null;
            if (context == null) {
                return;
            }

            // Media
            for (int i = 0; i < StorageVolumePreferenceCategory.sMediaCategories.length; i++) {
                if (mIsPrimary) {
                    String[] dirs = StorageVolumePreferenceCategory.sMediaCategories[i].mDirPaths;
                    final int length = dirs.length;
                    mMediaSizes[i] = 0;
                    for (int d = 0; d < length; d++) {
                        final String path = dirs[d];
                        mMediaSizes[i] += getDirectorySize(imcs, path);
                    }
                } else {
                    // TODO Compute sizes using the MediaStore
                    mMediaSizes[i] = 0;
                }
            }

            /* Compute sizes using the media provider
            // Media sizes are measured by the MediaStore. Query database.
            ContentResolver contentResolver = context.getContentResolver();
            // TODO "external" as a static String from MediaStore?
            Uri audioUri = MediaStore.Files.getContentUri("external");
            final String[] projection =
                new String[] { "sum(" + MediaStore.Files.FileColumns.SIZE + ")" };
            final String selection =
                MediaStore.Files.FileColumns.STORAGE_ID + "=" +
                Integer.toString(mStorageVolume.getStorageId()) + " AND " +
                MediaStore.Files.FileColumns.MEDIA_TYPE + "=?";

            for (int i = 0; i < StorageVolumePreferenceCategory.sMediaCategories.length; i++) {
                mMediaSizes[i] = 0;
                int mediaType = StorageVolumePreferenceCategory.sMediaCategories[i].mediaType;
                Cursor c = null;
                try {
                    c = contentResolver.query(audioUri, projection, selection,
                            new String[] { Integer.toString(mediaType) } , null);

                    if (c != null && c.moveToNext()) {
                        long size = c.getLong(0);
                        mMediaSizes[i] = size;
                    }
                } finally {
                    if (c != null) c.close();
                }
            }
             */

            // Downloads (primary volume only)
            if (mIsPrimary) {
                final String downloadsPath = Environment.getExternalStoragePublicDirectory(
                        Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
                mDownloadsSize = getDirectorySize(imcs, downloadsPath);
            } else {
                mDownloadsSize = 0;
            }

            // Misc
            mMiscSize = 0;
            if (mIsPrimary) {
                measureSizesOfMisc(imcs);
            }

            // Apps
            // We have to get installd to measure the package sizes.
            PackageManager pm = context.getPackageManager();
            if (pm == null) {
                return;
            }
            final List<ApplicationInfo> apps;
            if (mIsPrimary || mIsInternal) {
                apps = pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES |
                        PackageManager.GET_DISABLED_COMPONENTS);
            } else {
                // TODO also measure apps installed on the SD card
                apps = Collections.emptyList();
            }

            if (apps != null && apps.size() > 0) {
                // initiate measurement of all package sizes. need new StatsObserver object.
                mStatsObserver = new StatsObserver();
                synchronized (mStatsObserver.mAppsList) {
                    for (int i = 0; i < apps.size(); i++) {
                        final ApplicationInfo info = apps.get(i);
                        mStatsObserver.queuePackageMeasurementLocked(info.packageName);
                    }
                }

                requestQueuedMeasurementsLocked(pm);
                // Sending of the message back to the MeasurementReceiver is
                // completed in the PackageObserver
            } else {
                onInternalMeasurementComplete();
            }
        }
    }

    private long getDirectorySize(IMediaContainerService imcs, String dir) {
        try {
            return imcs.calculateDirectorySize(dir);
        } catch (Exception e) {
            Log.w(TAG, "Could not read memory from default container service for " + dir, e);
            return 0;
        }
    }

    long getMiscSize() {
        return mMiscSize;
    }

    private void measureSizesOfMisc(IMediaContainerService imcs) {
        File top = new File(mStorageVolume.getPath());
        mFileInfoForMisc = new ArrayList<FileInfo>();
        File[] files = top.listFiles();
        if (files == null) return;
        final int len = files.length;
        // Get sizes of all top level nodes except the ones already computed...
        long counter = 0;
        for (int i = 0; i < len; i++) {
            String path = files[i].getAbsolutePath();
            if (StorageVolumePreferenceCategory.sPathsExcludedForMisc.contains(path)) {
                continue;
            }
            if (files[i].isFile()) {
                final long fileSize = files[i].length();
                mFileInfoForMisc.add(new FileInfo(path, fileSize, counter++));
                mMiscSize += fileSize;
            } else if (files[i].isDirectory()) {
                final long dirSize = getDirectorySize(imcs, path);
                mFileInfoForMisc.add(new FileInfo(path, dirSize, counter++));
                mMiscSize += dirSize;
            } else {
                // Non directory, non file: not listed
            }
        }
        // sort the list of FileInfo objects collected above in descending order of their sizes
        Collections.sort(mFileInfoForMisc);
    }

    static class FileInfo implements Comparable<FileInfo> {
        final String mFileName;
        final long mSize;
        final long mId;

        FileInfo(String fileName, long size, long id) {
            mFileName = fileName;
            mSize = size;
            mId = id;
        }

        @Override
        public int compareTo(FileInfo that) {
            if (this == that || mSize == that.mSize) return 0;
            else return (mSize < that.mSize) ? 1 : -1; // for descending sort
        }

        @Override
        public String toString() {
            return mFileName  + " : " + mSize + ", id:" + mId;
        }
    }

    /**
     * TODO remove this method, only used because external SD Card needs a special treatment.
     */
    boolean isExternalSDCard() {
        return !mIsPrimary && !mIsInternal;
    }
}
