/*
 * 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.storagemanager.automatic;

import android.app.job.JobParameters;
import android.app.job.JobService;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.os.storage.StorageManager;
import android.provider.Settings;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.Utils;
import com.android.settingslib.deviceinfo.PrivateStorageInfo;
import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
import com.android.settingslib.deviceinfo.StorageVolumeProvider;
import com.android.storagemanager.overlay.FeatureFactory;
import com.android.storagemanager.overlay.StorageManagementJobProvider;

/**
 * {@link JobService} class to start automatic storage clearing jobs to free up space. The job only
 * starts if the device is under a certain percent of free storage.
 */
public class AutomaticStorageManagementJobService extends JobService {
    private static final String TAG = "AsmJobService";

    private static final long DEFAULT_LOW_FREE_PERCENT = 15;

    private StorageManagementJobProvider mProvider;
    private StorageVolumeProvider mVolumeProvider;
    private Clock mClock;

    @Override
    public boolean onStartJob(JobParameters args) {
        // We need to double-check the preconditions here because they are not enforced for a
        // periodic job.
        if (!preconditionsFulfilled()) {
            // By telling the system to re-schedule the job, it will attempt to execute again at a
            // later idle window -- possibly one where we are charging.
            jobFinished(args, true);
            return false;
        }

        mProvider = FeatureFactory.getFactory(this).getStorageManagementJobProvider();
        if (maybeDisableDueToPolicy(mProvider, this, getClock())) {
            jobFinished(args, false);
            return false;
        }

        if (!volumeNeedsManagement()) {
            Log.i(TAG, "Skipping automatic storage management.");
            Settings.Secure.putLong(getContentResolver(),
                    Settings.Secure.AUTOMATIC_STORAGE_MANAGER_LAST_RUN,
                    System.currentTimeMillis());
            jobFinished(args, false);
            return false;
        }

        if (!Utils.isStorageManagerEnabled(getApplicationContext())) {
            Intent maybeShowNotificationIntent =
                    new Intent(NotificationController.INTENT_ACTION_SHOW_NOTIFICATION);
            maybeShowNotificationIntent.setClass(getApplicationContext(),
                    NotificationController.class);
            getApplicationContext().sendBroadcast(maybeShowNotificationIntent);
            jobFinished(args, false);
            return false;
        }

        if (mProvider != null) {
            return mProvider.onStartJob(this, args, getDaysToRetain());
        }

        jobFinished(args, false);
        return false;
    }

    @Override
    public boolean onStopJob(JobParameters args) {
        if (mProvider != null) {
            return mProvider.onStopJob(this, args);
        }

        return false;
    }

    void setStorageVolumeProvider(StorageVolumeProvider storageProvider) {
        mVolumeProvider = storageProvider;
    }

    private int getDaysToRetain() {
        return Settings.Secure.getInt(
                getContentResolver(),
                Settings.Secure.AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
                Utils.getDefaultStorageManagerDaysToRetain(getResources()));
    }

    private boolean volumeNeedsManagement() {
        if (mVolumeProvider == null) {
            mVolumeProvider = new StorageManagerVolumeProvider(
                    getSystemService(StorageManager.class));
        }

        PrivateStorageInfo info = PrivateStorageInfo.getPrivateStorageInfo(mVolumeProvider);

        long lowStorageThreshold = (info.totalBytes * DEFAULT_LOW_FREE_PERCENT) / 100;
        return info.freeBytes < lowStorageThreshold;
    }

    private boolean preconditionsFulfilled() {
        // NOTE: We don't check the idle state here because this job should be running in idle
        // maintenance windows. During the idle maintenance window, the device is -technically- not
        // idle. For more information, see PowerManager.isDeviceIdleMode().
        Context context = getApplicationContext();
        return JobPreconditions.isCharging(context);
    }

    /** Returns if ASM was disabled due to policy. * */
    @VisibleForTesting
    static boolean maybeDisableDueToPolicy(
            StorageManagementJobProvider provider, Context context, Clock clock) {
        final ContentResolver cr = context.getContentResolver();
        if (provider == null || cr == null) {
            return false;
        }

        final long disabledThresholdMillis = provider.getDisableThresholdMillis(context);
        // Toss invalid thresholds.
        if (disabledThresholdMillis < 0) {
            return false;
        }

        final long currentTime = clock.currentTimeMillis();
        final boolean disabledByPolicyInThePast =
                Settings.Secure.getInt(
                                cr,
                                Settings.Secure.AUTOMATIC_STORAGE_MANAGER_TURNED_OFF_BY_POLICY,
                                0)
                        != 0;
        if (currentTime > disabledThresholdMillis && !disabledByPolicyInThePast) {
            Settings.Secure.putInt(
                    cr, Settings.Secure.AUTOMATIC_STORAGE_MANAGER_TURNED_OFF_BY_POLICY, 1);
            Settings.Secure.putInt(cr, Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED, 0);
            return true;
        }

        return false;
    }

    private Clock getClock() {
        if (mClock == null) {
            mClock = new Clock();
        }
        return mClock;
    }

    @VisibleForTesting
    void setClock(Clock clock) {
        mClock = clock;
    }

    /** Clock provides the current time. */
    protected static class Clock {
        /** Returns the current time in milliseconds. */
        public long currentTimeMillis() {
            return System.currentTimeMillis();
        }
    }
}
