/*
 * Copyright (C) 2016 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.telecom;

import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.provider.Settings;
import android.telecom.DefaultDialerManager;
import android.telecom.Log;
import android.util.SparseArray;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;

import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.function.IntConsumer;

public class DefaultDialerCache {
    public interface DefaultDialerManagerAdapter {
        String getDefaultDialerApplication(Context context);
        String getDefaultDialerApplication(Context context, int userId);
        boolean setDefaultDialerApplication(Context context, String packageName, int userId);
    }

    static class DefaultDialerManagerAdapterImpl implements DefaultDialerManagerAdapter {
        @Override
        public String getDefaultDialerApplication(Context context) {
            return DefaultDialerManager.getDefaultDialerApplication(context);
        }

        @Override
        public String getDefaultDialerApplication(Context context, int userId) {
            return DefaultDialerManager.getDefaultDialerApplication(context, userId);
        }

        @Override
        public boolean setDefaultDialerApplication(Context context, String packageName,
                int userId) {
            return DefaultDialerManager.setDefaultDialerApplication(context, packageName, userId);
        }
    }

    private static final String LOG_TAG = "DefaultDialerCache";
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.startSession("DDC.oR");
            try {
                String packageName;
                if (Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())) {
                    packageName = null;
                } else if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
                        && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
                    packageName = intent.getData().getSchemeSpecificPart();
                } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
                    packageName = null;
                } else if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
                    packageName = null;
                } else {
                    return;
                }

                synchronized (mLock) {
                    refreshCachesForUsersWithPackage(packageName);
                }

            } finally {
                Log.endSession();
            }
        }
    };

    private final BroadcastReceiver mUserRemovedReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
                int removedUser = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
                    UserHandle.USER_NULL);
                if (removedUser == UserHandle.USER_NULL) {
                    Log.w(LOG_TAG, "Expected EXTRA_USER_HANDLE with ACTION_USER_REMOVED");
                } else {
                    removeUserFromCache(removedUser);
                    Log.i(LOG_TAG, "Removing user %s", removedUser);
                }
            }
        }
    };

    private final Handler mHandler = new Handler(Looper.getMainLooper());
    private final ContentObserver mDefaultDialerObserver = new ContentObserver(mHandler) {
        @Override
        public void onChange(boolean selfChange) {
            Log.startSession("DDC.oC");
            try {
                // We don't get the user ID of the user that changed here, so we'll have to
                // refresh all of the users.
                synchronized (mLock) {
                    refreshCachesForUsersWithPackage(null);
                }
            } finally {
                Log.endSession();
            }
        }

        @Override
        public boolean deliverSelfNotifications() {
            return true;
        }
    };

    private final Context mContext;
    private final DefaultDialerManagerAdapter mDefaultDialerManagerAdapter;
    private final TelecomSystem.SyncRoot mLock;
    private final ComponentName mSystemDialerComponentName;
    private final RoleManagerAdapter mRoleManagerAdapter;
    private SparseArray<String> mCurrentDefaultDialerPerUser = new SparseArray<>();
    private ComponentName mOverrideSystemDialerComponentName;

    public DefaultDialerCache(Context context,
            DefaultDialerManagerAdapter defaultDialerManagerAdapter,
            RoleManagerAdapter roleManagerAdapter,
            TelecomSystem.SyncRoot lock) {
        mContext = context;
        mDefaultDialerManagerAdapter = defaultDialerManagerAdapter;
        mRoleManagerAdapter = roleManagerAdapter;
        mLock = lock;
        Resources resources = mContext.getResources();
        mSystemDialerComponentName = new ComponentName(resources.getString(
                com.android.internal.R.string.config_defaultDialer),
                resources.getString(R.string.incall_default_class));


        IntentFilter packageIntentFilter = new IntentFilter();
        packageIntentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
        packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
        packageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
        packageIntentFilter.addDataScheme("package");
        context.registerReceiverAsUser(mReceiver, UserHandle.ALL, packageIntentFilter, null, null);

        IntentFilter bootIntentFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
        context.registerReceiverAsUser(mReceiver, UserHandle.ALL, bootIntentFilter, null, null);

        IntentFilter userRemovedFilter = new IntentFilter(Intent.ACTION_USER_REMOVED);
        context.registerReceiver(mUserRemovedReceiver, userRemovedFilter);

        Uri defaultDialerSetting =
                Settings.Secure.getUriFor(Settings.Secure.DIALER_DEFAULT_APPLICATION);
        context.getContentResolver()
                .registerContentObserver(defaultDialerSetting, false, mDefaultDialerObserver,
                        UserHandle.USER_ALL);
    }

    public String getDefaultDialerApplication(int userId) {
        if (userId == UserHandle.USER_CURRENT) {
            userId = ActivityManager.getCurrentUser();
        }

        if (userId < 0) {
            Log.w(LOG_TAG, "Attempting to get default dialer for a meta-user %d", userId);
            return null;
        }

        // TODO: Re-enable this when we are able to use the cache once more.  RoleManager does not
        // provide a means for being informed when the role holder changes at the current time.
        //
        //synchronized (mLock) {
        //    String defaultDialer = mCurrentDefaultDialerPerUser.get(userId);
        //    if (defaultDialer != null) {
        //        return defaultDialer;
        //    }
        //}
        return refreshCacheForUser(userId);
    }

    public String getDefaultDialerApplication() {
        return getDefaultDialerApplication(mContext.getUserId());
    }

    public void setSystemDialerComponentName(ComponentName testComponentName) {
        mOverrideSystemDialerComponentName = testComponentName;
    }

    public String getSystemDialerApplication() {
        if (mOverrideSystemDialerComponentName != null) {
            return mOverrideSystemDialerComponentName.getPackageName();
        }
        return mSystemDialerComponentName.getPackageName();
    }

    public ComponentName getSystemDialerComponent() {
        if (mOverrideSystemDialerComponentName != null) return mOverrideSystemDialerComponentName;
        return mSystemDialerComponentName;
    }

    public ComponentName getDialtactsSystemDialerComponent() {
        final Resources resources = mContext.getResources();
        return new ComponentName(getSystemDialerApplication(),
                resources.getString(R.string.dialer_default_class));
    }

    public void observeDefaultDialerApplication(Executor executor, IntConsumer observer) {
        mRoleManagerAdapter.observeDefaultDialerApp(executor, observer);
    }

    public boolean isDefaultOrSystemDialer(String packageName, int userId) {
        String defaultDialer = getDefaultDialerApplication(userId);
        return Objects.equals(packageName, defaultDialer)
                || Objects.equals(packageName, getSystemDialerApplication());
    }

    public boolean setDefaultDialer(String packageName, int userId) {
        boolean isChanged = mDefaultDialerManagerAdapter.setDefaultDialerApplication(
                mContext, packageName, userId);
        if(isChanged) {
            synchronized (mLock) {
                // Update the cache synchronously so that there is no delay in cache update.
                mCurrentDefaultDialerPerUser.put(userId, packageName);
            }
        }
        return isChanged;
    }

    private String refreshCacheForUser(int userId) {
        String currentDefaultDialer =
                mRoleManagerAdapter.getDefaultDialerApp(userId);
        synchronized (mLock) {
            mCurrentDefaultDialerPerUser.put(userId, currentDefaultDialer);
        }
        return currentDefaultDialer;
    }

    /**
     * Refreshes the cache for users that currently have packageName as their cached default dialer.
     * If packageName is null, refresh all caches.
     * @param packageName Name of the affected package.
     */
    private void refreshCachesForUsersWithPackage(String packageName) {
        for (int i = 0; i < mCurrentDefaultDialerPerUser.size(); i++) {
            int userId = mCurrentDefaultDialerPerUser.keyAt(i);
            if (packageName == null ||
                    Objects.equals(packageName, mCurrentDefaultDialerPerUser.get(userId))) {
                String newDefaultDialer = refreshCacheForUser(userId);
                Log.i(LOG_TAG, "Refreshing default dialer for user %d: now %s",
                        userId, newDefaultDialer);
            }
        }
    }

    public void dumpCache(IndentingPrintWriter pw) {
        synchronized (mLock) {
            for (int i = 0; i < mCurrentDefaultDialerPerUser.size(); i++) {
                pw.printf("User %d: %s\n", mCurrentDefaultDialerPerUser.keyAt(i),
                        mCurrentDefaultDialerPerUser.valueAt(i));
            }
        }
    }

    private void removeUserFromCache(int userId) {
        synchronized (mLock) {
            mCurrentDefaultDialerPerUser.remove(userId);
        }
    }

    /**
     * registerContentObserver is really hard to mock out, so here is a getter method for the
     * content observer for testing instead.
     * @return The content observer
     */
    @VisibleForTesting
    public ContentObserver getContentObserver() {
        return mDefaultDialerObserver;
    }

    public RoleManagerAdapter getRoleManagerAdapter() {
        return mRoleManagerAdapter;
    }
}