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

import java.io.FileDescriptor;
import java.io.PrintWriter;

import com.android.nfc.ForegroundUtils;

import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.nfc.cardemulation.NfcFServiceInfo;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.os.SystemProperties;

public class EnabledNfcFServices implements com.android.nfc.ForegroundUtils.Callback {
    static final String TAG = "EnabledNfcFCardEmulationServices";
    static final boolean DBG = ((SystemProperties.get("persist.nfc.ce_debug").equals("1")) ? true : false);

    final Context mContext;
    final RegisteredNfcFServicesCache mNfcFServiceCache;
    final RegisteredT3tIdentifiersCache mT3tIdentifiersCache;
    final Callback mCallback;
    final ForegroundUtils mForegroundUtils = ForegroundUtils.getInstance();
    final Handler mHandler = new Handler(Looper.getMainLooper());

    final Object mLock = new Object();
    // Variables below synchronized on mLock
    ComponentName mForegroundComponent = null; // The computed enabled foreground component
    ComponentName mForegroundRequested = null; // The component requested to be enabled by fg app
    int mForegroundUid = -1; // The UID of the fg app, or -1 if fg app didn't request

    boolean mComputeFgRequested = false;
    boolean mActivated = false;

    public interface Callback {
        void onEnabledForegroundNfcFServiceChanged(ComponentName service);
    }

    public EnabledNfcFServices(Context context,
            RegisteredNfcFServicesCache nfcFServiceCache,
            RegisteredT3tIdentifiersCache t3tIdentifiersCache, Callback callback) {
        if (DBG) Log.d(TAG, "EnabledNfcFServices");
        mContext = context;
        mNfcFServiceCache = nfcFServiceCache;
        mT3tIdentifiersCache = t3tIdentifiersCache;
        mCallback = callback;
    }

    void computeEnabledForegroundService() {
        if (DBG) Log.d(TAG, "computeEnabledForegroundService");
        ComponentName foregroundRequested = null;
        boolean changed = false;
        synchronized (mLock) {
            if (mActivated) {
                Log.d(TAG, "configuration will be postponed until deactivation");
                mComputeFgRequested = true;
                return;
            }
            mComputeFgRequested = false;
            foregroundRequested = mForegroundRequested;
            if (mForegroundRequested != null &&
                    (mForegroundComponent == null ||
                    !mForegroundRequested.equals(mForegroundComponent))) {
                mForegroundComponent = mForegroundRequested;
                changed = true;
            } else if (mForegroundRequested == null && mForegroundComponent != null){
                mForegroundComponent = mForegroundRequested;
                changed = true;
            }
        }
        // Notify if anything changed
        if (changed) {
            mCallback.onEnabledForegroundNfcFServiceChanged(foregroundRequested);
        }
    }

    public void onServicesUpdated() {
        if (DBG) Log.d(TAG, "onServicesUpdated");
        // If enabled foreground service is set, remove it
        boolean changed = false;
        synchronized (mLock) {
            if (mForegroundComponent != null) {
                Log.d(TAG, "Removing foreground enabled service because of service update.");
                mForegroundRequested = null;
                mForegroundUid = -1;
                changed = true;
            }
        }
        if (changed) {
            computeEnabledForegroundService();
        }
    }

    public boolean registerEnabledForegroundService(ComponentName service, int callingUid) {
        if (DBG) Log.d(TAG, "registerEnabledForegroundService");
        boolean success = false;
        synchronized (mLock) {
            NfcFServiceInfo serviceInfo = mNfcFServiceCache.getService(
                    ActivityManager.getCurrentUser(), service);
            if (serviceInfo == null) {
                return false;
            } else {
                if (serviceInfo.getSystemCode().equalsIgnoreCase("NULL") ||
                        serviceInfo.getNfcid2().equalsIgnoreCase("NULL") ||
                        serviceInfo.getT3tPmm().equalsIgnoreCase("NULL")) {
                    return false;
                }
            }
            if (service.equals(mForegroundRequested)) {
                Log.e(TAG, "The servcie is already requested to the foreground service.");
                return true;
            }
            if (mForegroundUtils.registerUidToBackgroundCallback(this, callingUid)) {
                mForegroundRequested = service;
                mForegroundUid = callingUid;
                success = true;
            } else {
                Log.e(TAG, "Calling UID is not in the foreground, ignorning!");
            }
        }
        if (success) {
            computeEnabledForegroundService();
        }
        return success;
    }

    boolean unregisterForegroundService(int uid) {
        if (DBG) Log.d(TAG, "unregisterForegroundService");
        boolean success = false;
        synchronized (mLock) {
            if (mForegroundUid == uid) {
                mForegroundRequested = null;
                mForegroundUid = -1;
                success = true;
            } // else, other UID in foreground
        }
        if (success) {
            computeEnabledForegroundService();
        }
        return success;
    }

    public boolean unregisteredEnabledForegroundService(int callingUid) {
        if (DBG) Log.d(TAG, "unregisterEnabledForegroundService");
        // 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) {
        if (DBG) Log.d(TAG, "onUidToBackground");
        unregisterForegroundService(uid);
    }

    public void onHostEmulationActivated() {
        if (DBG) Log.d(TAG, "onHostEmulationActivated");
        synchronized (mLock) {
            mActivated = true;
        }
    }

    public void onHostEmulationDeactivated() {
        if (DBG) Log.d(TAG, "onHostEmulationDeactivated");
        boolean needComputeFg = false;
        synchronized (mLock) {
            mActivated = false;
            if (mComputeFgRequested) {
                needComputeFg = true;
            }
        }
        if (needComputeFg) {
            Log.d(TAG, "do postponed configuration");
            computeEnabledForegroundService();
        }
    }

    public void onNfcDisabled() {
        synchronized (mLock) {
            mForegroundComponent = null;
            mForegroundRequested = null;
            mActivated = false;
            mComputeFgRequested = false;
            mForegroundUid = -1;
        }
    }

    public void onUserSwitched(int userId) {
        synchronized (mLock) {
            mForegroundComponent = null;
            mForegroundRequested = null;
            mActivated = false;
            mComputeFgRequested = false;
            mForegroundUid = -1;
        }
    }

    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    }
}
