// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.util;

import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.support.v7.app.AlertDialog;
import android.view.accessibility.AccessibilityManager;

import org.chromium.base.PackageUtils;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.chrome.R;

import java.util.List;

/**
 * Exposes information about the current accessibility state
 */
public class AccessibilityUtil {
    // Whether we've already shown an alert that they have an old version of TalkBack running.
    private static boolean sOldTalkBackVersionAlertShown = false;

    // The link to download or update TalkBack from the Play Store.
    private static final String TALKBACK_MARKET_LINK =
            "market://search?q=pname:com.google.android.marvin.talkback";

    // The package name for TalkBack, an Android accessibility service.
    private static final String TALKBACK_PACKAGE_NAME =
            "com.google.android.marvin.talkback";

    // The minimum TalkBack version that we support. This is the version that shipped with
    // KitKat, from fall 2013. Versions older than that should be updated.
    private static final int MIN_TALKBACK_VERSION = 105;

    private AccessibilityUtil() { }

    /**
     * Checks to see that this device has accessibility and touch exploration enabled.
     * @param context A {@link Context} instance.
     * @return        Whether or not accessibility and touch exploration are enabled.
     */
    @CalledByNative
    public static boolean isAccessibilityEnabled(Context context) {
        AccessibilityManager manager = (AccessibilityManager)
                context.getSystemService(Context.ACCESSIBILITY_SERVICE);
        return manager != null && manager.isEnabled() && manager.isTouchExplorationEnabled();
    }

    /**
     * Checks to see if an old version of TalkBack is running that Chrome doesn't support,
     * and if so, shows an alert dialog prompting the user to update the app.
     * @param context A {@link Context} instance.
     * @return        True if the dialog was shown.
     */
    public static boolean showWarningIfOldTalkbackRunning(Context context) {
        AccessibilityManager manager = (AccessibilityManager)
                context.getSystemService(Context.ACCESSIBILITY_SERVICE);
        if (manager == null) return false;

        boolean isTalkbackRunning = false;
        try {
            List<AccessibilityServiceInfo> services =
                    manager.getEnabledAccessibilityServiceList(
                            AccessibilityServiceInfo.FEEDBACK_SPOKEN);
            for (AccessibilityServiceInfo service : services) {
                if (service.getId().contains(TALKBACK_PACKAGE_NAME)) isTalkbackRunning = true;
            }
        } catch (NullPointerException e) {
            // getEnabledAccessibilityServiceList() can throw an NPE due to a bad
            // AccessibilityService.
        }
        if (!isTalkbackRunning) return false;

        if (PackageUtils.getPackageVersion(context, TALKBACK_PACKAGE_NAME) < MIN_TALKBACK_VERSION
                && !sOldTalkBackVersionAlertShown) {
            showOldTalkbackVersionAlertOnce(context);
            return true;
        }

        return false;
    }

    private static void showOldTalkbackVersionAlertOnce(final Context context) {
        if (sOldTalkBackVersionAlertShown) return;
        sOldTalkBackVersionAlertShown = true;

        AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.AlertDialogTheme)
                .setTitle(R.string.old_talkback_title)
                .setPositiveButton(R.string.update_from_market,
                        new DialogInterface.OnClickListener() {
                        @Override
                            public void onClick(DialogInterface dialog, int id) {
                                Uri marketUri = Uri.parse(TALKBACK_MARKET_LINK);
                                Intent marketIntent = new Intent(
                                        Intent.ACTION_VIEW, marketUri);
                                context.startActivity(marketIntent);
                            }
                        })
                .setNegativeButton(R.string.cancel_talkback_alert,
                        new DialogInterface.OnClickListener() {
                        @Override
                            public void onClick(DialogInterface dialog, int id) {
                                // Do nothing, this alert is only shown once either way.
                            }
                        });
        AlertDialog dialog = builder.create();
        dialog.show();
    }
}