/*
 * 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.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.calName == 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();
        }
    };
}
