/*
 * Copyright (C) 2014 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.systemui.statusbar.policy;

import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings.Global;
import android.provider.Settings.Secure;
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.ZenRule;
import android.text.format.DateFormat;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dumpable;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.MainHandler;
import com.android.systemui.qs.GlobalSetting;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.util.Utils;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Objects;

import javax.inject.Inject;
import javax.inject.Singleton;

/** Platform implementation of the zen mode controller. **/
@Singleton
public class ZenModeControllerImpl extends CurrentUserTracker
        implements ZenModeController, Dumpable {
    private static final String TAG = "ZenModeController";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);

    private final ArrayList<Callback> mCallbacks = new ArrayList<>();
    private final Object mCallbacksLock = new Object();
    private final Context mContext;
    private final GlobalSetting mModeSetting;
    private final GlobalSetting mConfigSetting;
    private final NotificationManager mNoMan;
    private final AlarmManager mAlarmManager;
    private final SetupObserver mSetupObserver;
    private final UserManager mUserManager;

    private int mUserId;
    private boolean mRegistered;
    private ZenModeConfig mConfig;
    private int mZenMode;
    private long mZenUpdateTime;
    private NotificationManager.Policy mConsolidatedNotificationPolicy;

    @Inject
    public ZenModeControllerImpl(Context context, @MainHandler Handler handler,
            BroadcastDispatcher broadcastDispatcher) {
        super(broadcastDispatcher);
        mContext = context;
        mModeSetting = new GlobalSetting(mContext, handler, Global.ZEN_MODE) {
            @Override
            protected void handleValueChanged(int value) {
                updateZenMode(value);
                fireZenChanged(value);
            }
        };
        mConfigSetting = new GlobalSetting(mContext, handler, Global.ZEN_MODE_CONFIG_ETAG) {
            @Override
            protected void handleValueChanged(int value) {
                updateZenModeConfig();
            }
        };
        mNoMan = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        mModeSetting.setListening(true);
        updateZenMode(mModeSetting.getValue());
        mConfigSetting.setListening(true);
        updateZenModeConfig();
        updateConsolidatedNotificationPolicy();
        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        mSetupObserver = new SetupObserver(handler);
        mSetupObserver.register();
        mUserManager = context.getSystemService(UserManager.class);
        startTracking();
    }

    @Override
    public boolean isVolumeRestricted() {
        return mUserManager.hasUserRestriction(UserManager.DISALLOW_ADJUST_VOLUME,
                new UserHandle(mUserId));
    }

    @Override
    public boolean areNotificationsHiddenInShade() {
        if (mZenMode != Global.ZEN_MODE_OFF) {
            return (mConsolidatedNotificationPolicy.suppressedVisualEffects
                    & NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST) != 0;
        }
        return false;
    }

    @Override
    public void addCallback(Callback callback) {
        synchronized (mCallbacksLock) {
            mCallbacks.add(callback);
        }
    }

    @Override
    public void removeCallback(Callback callback) {
        synchronized (mCallbacksLock) {
            mCallbacks.remove(callback);
        }
    }

    @Override
    public int getZen() {
        return mZenMode;
    }

    @Override
    public void setZen(int zen, Uri conditionId, String reason) {
        mNoMan.setZenMode(zen, conditionId, reason);
    }

    @Override
    public boolean isZenAvailable() {
        return mSetupObserver.isDeviceProvisioned() && mSetupObserver.isUserSetup();
    }

    @Override
    public ZenRule getManualRule() {
        return mConfig == null ? null : mConfig.manualRule;
    }

    @Override
    public ZenModeConfig getConfig() {
        return mConfig;
    }

    @Override
    public NotificationManager.Policy getConsolidatedPolicy() {
        return mConsolidatedNotificationPolicy;
    }

    @Override
    public long getNextAlarm() {
        final AlarmManager.AlarmClockInfo info = mAlarmManager.getNextAlarmClock(mUserId);
        return info != null ? info.getTriggerTime() : 0;
    }

    @Override
    public void onUserSwitched(int userId) {
        mUserId = userId;
        if (mRegistered) {
            mContext.unregisterReceiver(mReceiver);
        }
        final IntentFilter filter = new IntentFilter(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
        filter.addAction(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED);
        mContext.registerReceiverAsUser(mReceiver, new UserHandle(mUserId), filter, null, null);
        mRegistered = true;
        mSetupObserver.register();
    }

    @Override
    public ComponentName getEffectsSuppressor() {
        return NotificationManager.from(mContext).getEffectsSuppressor();
    }

    @Override
    public boolean isCountdownConditionSupported() {
        return NotificationManager.from(mContext)
                .isSystemConditionProviderEnabled(ZenModeConfig.COUNTDOWN_PATH);
    }

    @Override
    public int getCurrentUser() {
        return ActivityManager.getCurrentUser();
    }

    private void fireNextAlarmChanged() {
        synchronized (mCallbacksLock) {
            Utils.safeForeach(mCallbacks, c -> c.onNextAlarmChanged());
        }
    }

    private void fireEffectsSuppressorChanged() {
        synchronized (mCallbacksLock) {
            Utils.safeForeach(mCallbacks, c -> c.onEffectsSupressorChanged());
        }
    }

    private void fireZenChanged(int zen) {
        synchronized (mCallbacksLock) {
            Utils.safeForeach(mCallbacks, c -> c.onZenChanged(zen));
        }
    }

    private void fireZenAvailableChanged(boolean available) {
        synchronized (mCallbacksLock) {
            Utils.safeForeach(mCallbacks, c -> c.onZenAvailableChanged(available));
        }
    }

    private void fireManualRuleChanged(ZenRule rule) {
        synchronized (mCallbacksLock) {
            Utils.safeForeach(mCallbacks, c -> c.onManualRuleChanged(rule));
        }
    }

    private void fireConsolidatedPolicyChanged(NotificationManager.Policy policy) {
        synchronized (mCallbacksLock) {
            Utils.safeForeach(mCallbacks, c -> c.onConsolidatedPolicyChanged(policy));
        }
    }

    @VisibleForTesting
    protected void fireConfigChanged(ZenModeConfig config) {
        synchronized (mCallbacksLock) {
            Utils.safeForeach(mCallbacks, c -> c.onConfigChanged(config));
        }
    }

    @VisibleForTesting
    protected void updateZenMode(int mode) {
        mZenMode = mode;
        mZenUpdateTime = System.currentTimeMillis();
    }

    @VisibleForTesting
    protected void updateConsolidatedNotificationPolicy() {
        final NotificationManager.Policy policy = mNoMan.getConsolidatedNotificationPolicy();
        if (!Objects.equals(policy, mConsolidatedNotificationPolicy)) {
            mConsolidatedNotificationPolicy = policy;
            fireConsolidatedPolicyChanged(policy);
        }
    }

    @VisibleForTesting
    protected void updateZenModeConfig() {
        final ZenModeConfig config = mNoMan.getZenModeConfig();
        if (Objects.equals(config, mConfig)) return;
        final ZenRule oldRule = mConfig != null ? mConfig.manualRule : null;
        mConfig = config;
        mZenUpdateTime = System.currentTimeMillis();
        fireConfigChanged(config);

        final ZenRule newRule = config != null ? config.manualRule : null;
        if (!Objects.equals(oldRule, newRule)) {
            fireManualRuleChanged(newRule);
        }

        final NotificationManager.Policy consolidatedPolicy =
                mNoMan.getConsolidatedNotificationPolicy();
        if (!Objects.equals(consolidatedPolicy, mConsolidatedNotificationPolicy)) {
            mConsolidatedNotificationPolicy = consolidatedPolicy;
            fireConsolidatedPolicyChanged(consolidatedPolicy);
        }

    }

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED.equals(intent.getAction())) {
                fireNextAlarmChanged();
            }
            if (NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED.equals(intent.getAction())) {
                fireEffectsSuppressorChanged();
            }
        }
    };

    @Override
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("ZenModeControllerImpl:");
        pw.println("  mZenMode=" + mZenMode);
        pw.println("  mConfig=" + mConfig);
        pw.println("  mConsolidatedNotificationPolicy=" + mConsolidatedNotificationPolicy);
        pw.println("  mZenUpdateTime=" + DateFormat.format("MM-dd HH:mm:ss", mZenUpdateTime));
    }

    private final class SetupObserver extends ContentObserver {
        private final ContentResolver mResolver;

        private boolean mRegistered;

        public SetupObserver(Handler handler) {
            super(handler);
            mResolver = mContext.getContentResolver();
        }

        public boolean isUserSetup() {
            return Secure.getIntForUser(mResolver, Secure.USER_SETUP_COMPLETE, 0, mUserId) != 0;
        }

        public boolean isDeviceProvisioned() {
            return Global.getInt(mResolver, Global.DEVICE_PROVISIONED, 0) != 0;
        }

        public void register() {
            if (mRegistered) {
                mResolver.unregisterContentObserver(this);
            }
            mResolver.registerContentObserver(
                    Global.getUriFor(Global.DEVICE_PROVISIONED), false, this);
            mResolver.registerContentObserver(
                    Secure.getUriFor(Secure.USER_SETUP_COMPLETE), false, this, mUserId);
            mRegistered = true;
            fireZenAvailableChanged(isZenAvailable());
        }

        @Override
        public void onChange(boolean selfChange, Uri uri) {
            if (Global.getUriFor(Global.DEVICE_PROVISIONED).equals(uri)
                    || Secure.getUriFor(Secure.USER_SETUP_COMPLETE).equals(uri)) {
                fireZenAvailableChanged(isZenAvailable());
            }
        }
    }
}
