/*
 * 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.nfc.cardemulation;

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

import com.android.nfc.ForegroundUtils;

import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.nfc.cardemulation.ApduServiceInfo;
import android.nfc.cardemulation.CardEmulation;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.Log;

/**
 * This class keeps track of what HCE/SE-based services are
 * preferred by the user. It currently has 3 inputs:
 * 1) The default set in tap&pay menu for payment category
 * 2) An app in the foreground asking for a specific
 *    service for a specific category
 * 3) If we had to disambiguate a previous tap (because no
 *    preferred service was there), we need to temporarily
 *    store the user's choice for the next tap.
 *
 * This class keeps track of all 3 inputs, and computes a new
 * preferred services as needed. It then passes this service
 * (if it changed) through a callback, which allows other components
 * to adapt as necessary (ie the AID cache can update its AID
 * mappings and the routing table).
 */
public class PreferredServices implements com.android.nfc.ForegroundUtils.Callback {
    static final String TAG = "PreferredCardEmulationServices";
    static final boolean DBG = false;
    static final Uri paymentDefaultUri = Settings.Secure.getUriFor(
            Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT);
    static final Uri paymentForegroundUri = Settings.Secure.getUriFor(
            Settings.Secure.NFC_PAYMENT_FOREGROUND);

    final SettingsObserver mSettingsObserver;
    final Context mContext;
    final RegisteredServicesCache mServiceCache;
    final RegisteredAidCache mAidCache;
    final Callback mCallback;
    final ForegroundUtils mForegroundUtils = ForegroundUtils.getInstance();
    final Handler mHandler = new Handler(Looper.getMainLooper());

    final class PaymentDefaults {
        boolean preferForeground; // The current selection mode for this category
        ComponentName settingsDefault; // The component preferred in settings (eg Tap&Pay)
        ComponentName currentPreferred; // The computed preferred component
    }

    final Object mLock = new Object();
    // Variables below synchronized on mLock
    PaymentDefaults mPaymentDefaults = new PaymentDefaults();

    ComponentName mForegroundRequested; // The component preferred by fg app
    int mForegroundUid; // The UID of the fg app, or -1 if fg app didn't request

    ComponentName mNextTapDefault; // The component preferred by active disambig dialog
    boolean mClearNextTapDefault = false; // Set when the next tap default must be cleared

    ComponentName mForegroundCurrent; // The currently computed foreground component

    public interface Callback {
        void onPreferredPaymentServiceChanged(ComponentName service);
        void onPreferredForegroundServiceChanged(ComponentName service);
    }

    public PreferredServices(Context context, RegisteredServicesCache serviceCache,
            RegisteredAidCache aidCache, Callback callback) {
        mContext = context;
        mServiceCache = serviceCache;
        mAidCache = aidCache;
        mCallback = callback;
        mSettingsObserver = new SettingsObserver(mHandler);
        mContext.getContentResolver().registerContentObserver(
                paymentDefaultUri,
                true, mSettingsObserver, UserHandle.USER_ALL);

        mContext.getContentResolver().registerContentObserver(
                paymentForegroundUri,
                true, mSettingsObserver, UserHandle.USER_ALL);

        // Load current settings defaults for payments
        loadDefaultsFromSettings(ActivityManager.getCurrentUser());
    }

    private final class SettingsObserver extends ContentObserver {
        public SettingsObserver(Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange, Uri uri) {
            super.onChange(selfChange, uri);
            // Do it just for the current user. If it was in fact
            // a change made for another user, we'll sync it down
            // on user switch.
            int currentUser = ActivityManager.getCurrentUser();
            loadDefaultsFromSettings(currentUser);
        }
    };

    void loadDefaultsFromSettings(int userId) {
        boolean paymentDefaultChanged = false;
        boolean paymentPreferForegroundChanged = false;
        // Load current payment default from settings
        String name = Settings.Secure.getStringForUser(
                mContext.getContentResolver(), Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT,
                userId);
        ComponentName newDefault = name != null ? ComponentName.unflattenFromString(name) : null;
        boolean preferForeground = false;
        try {
            preferForeground = Settings.Secure.getIntForUser(mContext.getContentResolver(),
                    Settings.Secure.NFC_PAYMENT_FOREGROUND, userId) != 0;
        } catch (SettingNotFoundException e) {
        }
        synchronized (mLock) {
            paymentPreferForegroundChanged = (preferForeground != mPaymentDefaults.preferForeground);
            mPaymentDefaults.preferForeground = preferForeground;

            mPaymentDefaults.settingsDefault = newDefault;
            if (newDefault != null && !newDefault.equals(mPaymentDefaults.currentPreferred)) {
                paymentDefaultChanged = true;
                mPaymentDefaults.currentPreferred = newDefault;
            } else if (newDefault == null && mPaymentDefaults.currentPreferred != null) {
                paymentDefaultChanged = true;
                mPaymentDefaults.currentPreferred = newDefault;
            } else {
                // Same default as before
            }
        }
        // Notify if anything changed
        if (paymentDefaultChanged) {
            mCallback.onPreferredPaymentServiceChanged(newDefault);
        }
        if (paymentPreferForegroundChanged) {
            computePreferredForegroundService();
        }
    }

    void computePreferredForegroundService() {
        ComponentName preferredService = null;
        boolean changed = false;
        synchronized (mLock) {
            // Prio 1: next tap default
            preferredService = mNextTapDefault;
            if (preferredService == null) {
                // Prio 2: foreground requested by app
                preferredService = mForegroundRequested;
            }
            if (preferredService != null && !preferredService.equals(mForegroundCurrent)) {
                mForegroundCurrent = preferredService;
                changed = true;
            } else if (preferredService == null && mForegroundCurrent != null){
                mForegroundCurrent = preferredService;
                changed = true;
            }
        }
        // Notify if anything changed
        if (changed) {
            mCallback.onPreferredForegroundServiceChanged(preferredService);
        }
    }

    public boolean setDefaultForNextTap(ComponentName service) {
        // This is a trusted API, so update without checking
        synchronized (mLock) {
            mNextTapDefault = service;
        }
        computePreferredForegroundService();
        return true;
    }

    public void onServicesUpdated() {
        // If this service is the current foreground service, verify
        // there are no conflicts
        boolean changed = false;
        synchronized (mLock) {
            // Check if the current foreground service is still allowed to override;
            // it could have registered new AIDs that make it conflict with user
            // preferences.
            if (mForegroundCurrent != null) {
                if (!isForegroundAllowedLocked(mForegroundCurrent))  {
                    Log.d(TAG, "Removing foreground preferred service.");
                    mForegroundRequested = null;
                    mForegroundUid = -1;
                    changed = true;
                }
            } else {
                // Don't care about this service
            }
        }
        if (changed) {
            computePreferredForegroundService();
        }
    }

    // Verifies whether a service is allowed to register as preferred
    boolean isForegroundAllowedLocked(ComponentName service) {
        if (service.equals(mPaymentDefaults.currentPreferred)) {
            // If the requester is already the payment default, allow it to request foreground
            // override as well (it could use this to make sure it handles AIDs of category OTHER)
            return true;
        }
        ApduServiceInfo serviceInfo = mServiceCache.getService(ActivityManager.getCurrentUser(),
                service);
        if (serviceInfo == null) {
            Log.d(TAG, "Requested foreground service unexpectedly removed");
            return false;
        }
        // Do some sanity checking
        if (!mPaymentDefaults.preferForeground) {
            // Foreground apps are not allowed to override payment default
            // Check if this app registers payment AIDs, in which case we'll fail anyway
            if (serviceInfo.hasCategory(CardEmulation.CATEGORY_PAYMENT)) {
                Log.d(TAG, "User doesn't allow payment services to be overridden.");
                return false;
            }
            // If no payment AIDs, get AIDs of category other, and see if there's any
            // conflict with payment AIDs of current default payment app. That means
            // the current default payment app said this was a payment AID, and the
            // foreground app says it was not. In this case we'll still prefer the payment
            // app, since that is the one that the user has explicitly selected (and said
            // it's not allowed to be overridden).
            final List<String> otherAids = serviceInfo.getAids();
            ApduServiceInfo paymentServiceInfo = mServiceCache.getService(
                    ActivityManager.getCurrentUser(), mPaymentDefaults.currentPreferred);
            if (paymentServiceInfo != null && otherAids != null && otherAids.size() > 0) {
                for (String aid : otherAids) {
                    RegisteredAidCache.AidResolveInfo resolveInfo = mAidCache.resolveAid(aid);
                    if (CardEmulation.CATEGORY_PAYMENT.equals(resolveInfo.category) &&
                            paymentServiceInfo.equals(resolveInfo.defaultService)) {
                        if (DBG) Log.d(TAG, "AID " + aid + " is handled by the default payment app,"
                                + " and the user has not allowed payments to be overridden.");
                        return false;
                    }
                }
                return true;
            } else {
                // Could not find payment service or fg app doesn't register other AIDs;
                // okay to proceed.
                return true;
            }
        } else {
            // Payment allows override, so allow anything.
            return true;
        }
    }

    public boolean registerPreferredForegroundService(ComponentName service, int callingUid) {
        boolean success = false;
        synchronized (mLock) {
            if (isForegroundAllowedLocked(service)) {
                if (mForegroundUtils.registerUidToBackgroundCallback(this, callingUid)) {
                    mForegroundRequested = service;
                    mForegroundUid = callingUid;
                    success = true;
                } else {
                    Log.e(TAG, "Calling UID is not in the foreground, ignorning!");
                    success = false;
                }
            } else {
                Log.e(TAG, "Requested foreground service conflicts or was removed.");
            }
        }
        if (success) {
            computePreferredForegroundService();
        }
        return success;
    }

    boolean unregisterForegroundService(int uid) {
        boolean success = false;
        synchronized (mLock) {
            if (mForegroundUid == uid) {
                mForegroundRequested = null;
                mForegroundUid = -1;
                success = true;
            } // else, other UID in foreground
        }
        if (success) {
            computePreferredForegroundService();
        }
        return success;
    }

    public boolean unregisteredPreferredForegroundService(int callingUid) {
        // Verify the calling UID is in the foreground
        if (mForegroundUtils.isInForeground(callingUid)) {
            return unregisterForegroundService(callingUid);
        } else {
            Log.e(TAG, "Calling UID is not in the foreground, ignorning!");
            return false;
        }
    }

    @Override
    public void onUidToBackground(int uid) {
        unregisterForegroundService(uid);
    }

    public void onHostEmulationActivated() {
        synchronized (mLock) {
            mClearNextTapDefault = (mNextTapDefault != null);
        }
    }

    public void onHostEmulationDeactivated() {
        // If we had any next tap defaults set, clear them out
        boolean changed = false;
        synchronized (mLock) {
            if (mClearNextTapDefault) {
                // The reason we need to check this boolean is because the next tap
                // default may have been set while the user held the phone
                // on the reader; when the user then removes his phone from
                // the reader (causing the "onHostEmulationDeactivated" event),
                // the next tap default would immediately be cleared
                // again. Instead, clear out defaults only if a next tap default
                // had already been set at time of activation, which is captured
                // by mClearNextTapDefault.
                if (mNextTapDefault != null) {
                    mNextTapDefault = null;
                    changed = true;
                }
                mClearNextTapDefault = false;
            }
        }
        if (changed) {
            computePreferredForegroundService();
        }
    }

    public void onUserSwitched(int userId) {
        loadDefaultsFromSettings(userId);
    }

    public boolean packageHasPreferredService(String packageName) {
        if (packageName == null) return false;

        if (mPaymentDefaults.currentPreferred != null &&
                packageName.equals(mPaymentDefaults.currentPreferred.getPackageName())) {
            return true;
        } else if (mForegroundCurrent != null &&
                packageName.equals(mForegroundCurrent.getPackageName())) {
            return true;
        } else {
            return false;
        }
    }

    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("Preferred services (in order of importance): ");
        pw.println("    *** Current preferred foreground service: " + mForegroundCurrent);
        pw.println("    *** Current preferred payment service: " + mPaymentDefaults.currentPreferred);
        pw.println("        Next tap default: " + mNextTapDefault);
        pw.println("        Default for foreground app (UID: " + mForegroundUid +
                "): " + mForegroundRequested);
        pw.println("        Default in payment settings: " + mPaymentDefaults.settingsDefault);
        pw.println("        Payment settings allows override: " + mPaymentDefaults.preferForeground);
        pw.println("");
    }
}
