// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.nasa.pic.customtab;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

/**
 * Helper class for Custom Tabs.
 */
public class CustomTabsHelper {
	private static final String TAG = "CustomTabsHelper";
	static final String STABLE_PACKAGE = "com.android.chrome";
	static final String BETA_PACKAGE = "com.chrome.beta";
	static final String DEV_PACKAGE = "com.chrome.dev";
	static final String LOCAL_PACKAGE = "com.google.android.apps.chrome";
	private static final String ACTION_CUSTOM_TABS_CONNECTION =
			"android.support.customtabs.action.CustomTabsService";

	private static String sPackageNameToUse;

	private CustomTabsHelper() {}


	/**
	 * Goes through all apps that handle VIEW intents and have a warmup service. Picks
	 * the one chosen by the user if there is one, otherwise makes a best effort to return a
	 * valid package name.
	 *
	 * This is <strong>not</strong> threadsafe.
	 *
	 * @param context {@link Context} to use for accessing {@link PackageManager}.
	 * @return The package name recommended to use for connecting to custom tabs related components.
	 */
	public static String getPackageNameToUse(Context context) {
		if (sPackageNameToUse != null) return sPackageNameToUse;

		PackageManager pm = context.getPackageManager();
		// Get default VIEW intent handler.
		Intent activityIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com"));
		ResolveInfo defaultViewHandlerInfo = pm.resolveActivity(activityIntent, 0);
		String defaultViewHandlerPackageName = null;
		if (defaultViewHandlerInfo != null) {
			defaultViewHandlerPackageName = defaultViewHandlerInfo.activityInfo.packageName;
		}

		// Get all apps that can handle VIEW intents.
		List<ResolveInfo> resolvedActivityList = pm.queryIntentActivities(activityIntent, 0);
		List<String> packagesSupportingCustomTabs = new ArrayList<>();
		for (ResolveInfo info : resolvedActivityList) {
			Intent serviceIntent = new Intent();
			serviceIntent.setAction(ACTION_CUSTOM_TABS_CONNECTION);
			serviceIntent.setPackage(info.activityInfo.packageName);
			if (pm.resolveService(serviceIntent, 0) != null) {
				packagesSupportingCustomTabs.add(info.activityInfo.packageName);
			}
		}

		// Now packagesSupportingCustomTabs contains all apps that can handle both VIEW intents
		// and service calls.
		if (packagesSupportingCustomTabs.isEmpty()) {
			sPackageNameToUse = null;
		} else if (packagesSupportingCustomTabs.size() == 1) {
			sPackageNameToUse = packagesSupportingCustomTabs.get(0);
		} else if (!TextUtils.isEmpty(defaultViewHandlerPackageName)
				&& !hasSpecializedHandlerIntents(context, activityIntent)
				&& packagesSupportingCustomTabs.contains(defaultViewHandlerPackageName)) {
			sPackageNameToUse = defaultViewHandlerPackageName;
		} else if (packagesSupportingCustomTabs.contains(STABLE_PACKAGE)) {
			sPackageNameToUse = STABLE_PACKAGE;
		} else if (packagesSupportingCustomTabs.contains(BETA_PACKAGE)) {
			sPackageNameToUse = BETA_PACKAGE;
		} else if (packagesSupportingCustomTabs.contains(DEV_PACKAGE)) {
			sPackageNameToUse = DEV_PACKAGE;
		} else if (packagesSupportingCustomTabs.contains(LOCAL_PACKAGE)) {
			sPackageNameToUse = LOCAL_PACKAGE;
		}
		return sPackageNameToUse;
	}

	/**
	 * Used to check whether there is a specialized handler for a given intent.
	 * @param intent The intent to check with.
	 * @return Whether there is a specialized handler for the given intent.
	 */
	private static boolean hasSpecializedHandlerIntents(Context context, Intent intent) {
		try {
			PackageManager pm = context.getPackageManager();
			List<ResolveInfo> handlers = pm.queryIntentActivities(
					intent,
					PackageManager.GET_RESOLVED_FILTER);
			if (handlers == null || handlers.size() == 0) {
				return false;
			}
			for (ResolveInfo resolveInfo : handlers) {
				IntentFilter filter = resolveInfo.filter;
				if (filter == null) continue;
				if (filter.countDataAuthorities() == 0 || filter.countDataPaths() == 0) continue;
				if (resolveInfo.activityInfo == null) continue;
				return true;
			}
		} catch (RuntimeException e) {
			Log.e(TAG, "Runtime exception while getting specialized handlers");
		}
		return false;
	}


}