/*
 * 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.server.notification;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.service.notification.Condition;
import android.service.notification.IConditionProvider;
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.EventInfo;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;

import com.android.server.notification.CalendarTracker.CheckEventResult;
import com.android.server.notification.NotificationManagerService.DumpFilter;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

/**
 * Built-in zen condition provider for calendar event-based conditions.
 */
public class EventConditionProvider extends SystemConditionProviderService {
    private static final String TAG = "ConditionProviders.ECP";
    private static final boolean DEBUG = Log.isLoggable("ConditionProviders", Log.DEBUG);

    public static final ComponentName COMPONENT =
            new ComponentName("android", EventConditionProvider.class.getName());
    private static final String NOT_SHOWN = "...";
    private static final String SIMPLE_NAME = EventConditionProvider.class.getSimpleName();
    private static final String ACTION_EVALUATE = SIMPLE_NAME + ".EVALUATE";
    private static final int REQUEST_CODE_EVALUATE = 1;
    private static final String EXTRA_TIME = "time";
    private static final long CHANGE_DELAY = 2 * 1000;  // coalesce chatty calendar changes

    private final Context mContext = this;
    private final ArraySet<Uri> mSubscriptions = new ArraySet<Uri>();
    private final SparseArray<CalendarTracker> mTrackers = new SparseArray<>();
    private final Handler mWorker;
    private final HandlerThread mThread;

    private boolean mConnected;
    private boolean mRegistered;
    private boolean mBootComplete;  // don't hammer the calendar provider until boot completes.
    private long mNextAlarmTime;

    public EventConditionProvider() {
        if (DEBUG) Slog.d(TAG, "new " + SIMPLE_NAME + "()");
        mThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
        mThread.start();
        mWorker = new Handler(mThread.getLooper());
    }

    @Override
    public ComponentName getComponent() {
        return COMPONENT;
    }

    @Override
    public boolean isValidConditionId(Uri id) {
        return ZenModeConfig.isValidEventConditionId(id);
    }

    @Override
    public void dump(PrintWriter pw, DumpFilter filter) {
        pw.print("    "); pw.print(SIMPLE_NAME); pw.println(":");
        pw.print("      mConnected="); pw.println(mConnected);
        pw.print("      mRegistered="); pw.println(mRegistered);
        pw.print("      mBootComplete="); pw.println(mBootComplete);
        dumpUpcomingTime(pw, "mNextAlarmTime", mNextAlarmTime, System.currentTimeMillis());
        synchronized (mSubscriptions) {
            pw.println("      mSubscriptions=");
            for (Uri conditionId : mSubscriptions) {
                pw.print("        ");
                pw.println(conditionId);
            }
        }
        pw.println("      mTrackers=");
        for (int i = 0; i < mTrackers.size(); i++) {
            pw.print("        user="); pw.println(mTrackers.keyAt(i));
            mTrackers.valueAt(i).dump("          ", pw);
        }
    }

    @Override
    public void onBootComplete() {
        if (DEBUG) Slog.d(TAG, "onBootComplete");
        if (mBootComplete) return;
        mBootComplete = true;
        final IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
        filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
        mContext.registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                reloadTrackers();
            }
        }, filter);
        reloadTrackers();
    }

    @Override
    public void onConnected() {
        if (DEBUG) Slog.d(TAG, "onConnected");
        mConnected = true;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (DEBUG) Slog.d(TAG, "onDestroy");
        mConnected = false;
    }

    @Override
    public void onSubscribe(Uri conditionId) {
        if (DEBUG) Slog.d(TAG, "onSubscribe " + conditionId);
        if (!ZenModeConfig.isValidEventConditionId(conditionId)) {
            notifyCondition(createCondition(conditionId, Condition.STATE_FALSE));
            return;
        }
        synchronized (mSubscriptions) {
            if (mSubscriptions.add(conditionId)) {
                evaluateSubscriptions();
            }
        }
    }

    @Override
    public void onUnsubscribe(Uri conditionId) {
        if (DEBUG) Slog.d(TAG, "onUnsubscribe " + conditionId);
        synchronized (mSubscriptions) {
            if (mSubscriptions.remove(conditionId)) {
                evaluateSubscriptions();
            }
        }
    }

    @Override
    public void attachBase(Context base) {
        attachBaseContext(base);
    }

    @Override
    public IConditionProvider asInterface() {
        return (IConditionProvider) onBind(null);
    }

    private void reloadTrackers() {
        if (DEBUG) Slog.d(TAG, "reloadTrackers");
        for (int i = 0; i < mTrackers.size(); i++) {
            mTrackers.valueAt(i).setCallback(null);
        }
        mTrackers.clear();
        for (UserHandle user : UserManager.get(mContext).getUserProfiles()) {
            final Context context = user.isSystem() ? mContext : getContextForUser(mContext, user);
            if (context == null) {
                Slog.w(TAG, "Unable to create context for user " + user.getIdentifier());
                continue;
            }
            mTrackers.put(user.getIdentifier(), new CalendarTracker(mContext, context));
        }
        evaluateSubscriptions();
    }

    private void evaluateSubscriptions() {
        if (!mWorker.hasCallbacks(mEvaluateSubscriptionsW)) {
            mWorker.post(mEvaluateSubscriptionsW);
        }
    }

    private void evaluateSubscriptionsW() {
        if (DEBUG) Slog.d(TAG, "evaluateSubscriptions");
        if (!mBootComplete) {
            if (DEBUG) Slog.d(TAG, "Skipping evaluate before boot complete");
            return;
        }
        final long now = System.currentTimeMillis();
        List<Condition> conditionsToNotify = new ArrayList<>();
        synchronized (mSubscriptions) {
            for (int i = 0; i < mTrackers.size(); i++) {
                mTrackers.valueAt(i).setCallback(
                        mSubscriptions.isEmpty() ? null : mTrackerCallback);
            }
            setRegistered(!mSubscriptions.isEmpty());
            long reevaluateAt = 0;
            for (Uri conditionId : mSubscriptions) {
                final EventInfo event = ZenModeConfig.tryParseEventConditionId(conditionId);
                if (event == null) {
                    conditionsToNotify.add(createCondition(conditionId, Condition.STATE_FALSE));
                    continue;
                }
                CheckEventResult result = null;
                if (event.calendar == null) { // any calendar
                    // event could exist on any tracker
                    for (int i = 0; i < mTrackers.size(); i++) {
                        final CalendarTracker tracker = mTrackers.valueAt(i);
                        final CheckEventResult r = tracker.checkEvent(event, now);
                        if (result == null) {
                            result = r;
                        } else {
                            result.inEvent |= r.inEvent;
                            result.recheckAt = Math.min(result.recheckAt, r.recheckAt);
                        }
                    }
                } else {
                    // event should exist on one tracker
                    final int userId = EventInfo.resolveUserId(event.userId);
                    final CalendarTracker tracker = mTrackers.get(userId);
                    if (tracker == null) {
                        Slog.w(TAG, "No calendar tracker found for user " + userId);
                        conditionsToNotify.add(createCondition(conditionId, Condition.STATE_FALSE));
                        continue;
                    }
                    result = tracker.checkEvent(event, now);
                }
                if (result.recheckAt != 0
                        && (reevaluateAt == 0 || result.recheckAt < reevaluateAt)) {
                    reevaluateAt = result.recheckAt;
                }
                if (!result.inEvent) {
                    conditionsToNotify.add(createCondition(conditionId, Condition.STATE_FALSE));
                    continue;
                }
                conditionsToNotify.add(createCondition(conditionId, Condition.STATE_TRUE));
            }
            rescheduleAlarm(now, reevaluateAt);
        }
        for (Condition condition : conditionsToNotify) {
            if (condition != null) {
                notifyCondition(condition);
            }
        }
        if (DEBUG) Slog.d(TAG, "evaluateSubscriptions took " + (System.currentTimeMillis() - now));
    }

    private void rescheduleAlarm(long now, long time) {
        mNextAlarmTime = time;
        final AlarmManager alarms = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
        final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext,
                REQUEST_CODE_EVALUATE,
                new Intent(ACTION_EVALUATE)
                        .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
                        .putExtra(EXTRA_TIME, time),
                PendingIntent.FLAG_UPDATE_CURRENT);
        alarms.cancel(pendingIntent);
        if (time == 0 || time < now) {
            if (DEBUG) Slog.d(TAG, "Not scheduling evaluate: " + (time == 0 ? "no time specified"
                    : "specified time in the past"));
            return;
        }
        if (DEBUG) Slog.d(TAG, String.format("Scheduling evaluate for %s, in %s, now=%s",
                ts(time), formatDuration(time - now), ts(now)));
        alarms.setExact(AlarmManager.RTC_WAKEUP, time, pendingIntent);
    }

    private Condition createCondition(Uri id, int state) {
        final String summary = NOT_SHOWN;
        final String line1 = NOT_SHOWN;
        final String line2 = NOT_SHOWN;
        return new Condition(id, summary, line1, line2, 0, state, Condition.FLAG_RELEVANT_ALWAYS);
    }

    private void setRegistered(boolean registered) {
        if (mRegistered == registered) return;
        if (DEBUG) Slog.d(TAG, "setRegistered " + registered);
        mRegistered = registered;
        if (mRegistered) {
            final IntentFilter filter = new IntentFilter();
            filter.addAction(Intent.ACTION_TIME_CHANGED);
            filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
            filter.addAction(ACTION_EVALUATE);
            registerReceiver(mReceiver, filter);
        } else {
            unregisterReceiver(mReceiver);
        }
    }

    private static Context getContextForUser(Context context, UserHandle user) {
        try {
            return context.createPackageContextAsUser(context.getPackageName(), 0, user);
        } catch (NameNotFoundException e) {
            return null;
        }
    }

    private final CalendarTracker.Callback mTrackerCallback = new CalendarTracker.Callback() {
        @Override
        public void onChanged() {
            if (DEBUG) Slog.d(TAG, "mTrackerCallback.onChanged");
            mWorker.removeCallbacks(mEvaluateSubscriptionsW);
            mWorker.postDelayed(mEvaluateSubscriptionsW, CHANGE_DELAY);
        }
    };

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (DEBUG) Slog.d(TAG, "onReceive " + intent.getAction());
            evaluateSubscriptions();
        }
    };

    private final Runnable mEvaluateSubscriptionsW = new Runnable() {
        @Override
        public void run() {
            evaluateSubscriptionsW();
        }
    };
}
