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

import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.os.UserManager;
import android.provider.Settings;
import android.telephony.PhoneNumberUtils;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.WindowManager;

import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.TelephonyCapabilities;

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

/**
 * Helper class to listen for some magic dialpad character sequences
 * that are handled specially by the Phone app.
 *
 * Note the Contacts app also handles these sequences too, so there's a
 * separate version of this class under apps/Contacts.
 *
 * In fact, the most common use case for these special sequences is typing
 * them from the regular "Dialer" used for outgoing calls, which is part
 * of the contacts app; see DialtactsActivity and DialpadFragment.
 * *This* version of SpecialCharSequenceMgr is used for only a few
 * relatively obscure places in the UI:
 * - The "SIM network unlock" PIN entry screen (see
 *   IccNetworkDepersonalizationPanel.java)
 * - The emergency dialer (see EmergencyDialer.java).
 *
 * TODO: there's lots of duplicated code between this class and the
 * corresponding class under apps/Contacts.  Let's figure out a way to
 * unify these two classes (in the framework? in a common shared library?)
 */
public class SpecialCharSequenceMgr {
    private static final String TAG = PhoneGlobals.LOG_TAG;
    private static final boolean DBG = false;

    private static final String MMI_IMEI_DISPLAY = "*#06#";
    private static final String MMI_REGULATORY_INFO_DISPLAY = "*#07#";

    /** This class is never instantiated. */
    private SpecialCharSequenceMgr() {
    }

    /**
     * Check for special strings of digits from an input
     * string.
     * @param context input Context for the events we handle.
     * @param input the dial string to be examined.
     */
    static boolean handleChars(Context context, String input) {
        return handleChars(context, input, null);
    }

    /**
     * Generally used for the Personal Unblocking Key (PUK) unlocking
     * case, where we want to be able to maintain a handle to the
     * calling activity so that we can close it or otherwise display
     * indication if the PUK code is recognized.
     *
     * NOTE: The counterpart to this file in Contacts does
     * NOT contain the special PUK handling code, since it
     * does NOT need it.  When the device gets into PUK-
     * locked state, the keyguard comes up and the only way
     * to unlock the device is through the Emergency dialer,
     * which is still in the Phone App.
     *
     * @param context input Context for the events we handle.
     * @param input the dial string to be examined.
     * @param pukInputActivity activity that originated this
     * PUK call, tracked so that we can close it or otherwise
     * indicate that special character sequence is
     * successfully processed. Can be null.
     * @return true if the input was a special string which has been
     * handled.
     */
    static boolean handleChars(Context context,
                               String input,
                               Activity pukInputActivity) {

        //get rid of the separators so that the string gets parsed correctly
        String dialString = PhoneNumberUtils.stripSeparators(input);

        if (handleIMEIDisplay(context, dialString)
            || handleRegulatoryInfoDisplay(context, dialString)
            || handlePinEntry(context, dialString, pukInputActivity)
            || handleAdnEntry(context, dialString)
            || handleSecretCode(dialString)) {
            return true;
        }

        return false;
    }

    /**
     * Variant of handleChars() that looks for the subset of "special
     * sequences" that are available even if the device is locked.
     *
     * (Specifically, these are the sequences that you're allowed to type
     * in the Emergency Dialer, which is accessible *without* unlocking
     * the device.)
     */
    static boolean handleCharsForLockedDevice(Context context,
                                              String input,
                                              Activity pukInputActivity) {
        // Get rid of the separators so that the string gets parsed correctly
        String dialString = PhoneNumberUtils.stripSeparators(input);

        // The only sequences available on a locked device are the "**04"
        // or "**05" sequences that allow you to enter PIN or PUK-related
        // codes.  (e.g. for the case where you're currently locked out of
        // your phone, and need to change the PIN!  The only way to do
        // that is via the Emergency Dialer.)

        if (handlePinEntry(context, dialString, pukInputActivity)) {
            return true;
        }

        return false;
    }

    /**
     * Handles secret codes to launch arbitrary receivers in the form of *#*#<code>#*#*.
     * If a secret code is encountered, an broadcast intent is sent with the
     * android_secret_code://<code> URI.
     *
     * @param input the text to check for a secret code in
     * @return true if a secret code was encountered and intent is sent out
     */
    static private boolean handleSecretCode(String input) {
        // Secret codes are in the form *#*#<code>#*#*
        int len = input.length();
        if (len > 8 && input.startsWith("*#*#") && input.endsWith("#*#*")) {
            final Phone phone = PhoneGlobals.getPhone();
            phone.sendDialerSpecialCode(input.substring(4, len - 4));
            return true;
        }
        return false;
    }

    static private boolean handleAdnEntry(Context context, String input) {
        /* ADN entries are of the form "N(N)(N)#" */

        // if the phone is keyguard-restricted, then just ignore this
        // input.  We want to make sure that sim card contacts are NOT
        // exposed unless the phone is unlocked, and this code can be
        // accessed from the emergency dialer.
        if (PhoneGlobals.getInstance().getKeyguardManager().inKeyguardRestrictedInputMode()) {
            return false;
        }

        int len = input.length();
        if ((len > 1) && (len < 5) && (input.endsWith("#"))) {
            try {
                int index = Integer.parseInt(input.substring(0, len-1));
                Intent intent = new Intent(Intent.ACTION_PICK);

                intent.setClassName("com.android.phone",
                                    "com.android.phone.SimContacts");
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.putExtra("index", index);
                PhoneGlobals.getInstance().startActivity(intent);

                return true;
            } catch (NumberFormatException ex) {}
        }
        return false;
    }

    private static IccCardConstants.State getSimState(int slotId, Context context) {
        final TelephonyManager tele = TelephonyManager.from(context);
        int simState =  tele.getSimState(slotId);
        IccCardConstants.State state;
        try {
            state = IccCardConstants.State.intToState(simState);
        } catch (IllegalArgumentException ex) {
            Log.w(TAG, "Unknown sim state: " + simState);
            state = IccCardConstants.State.UNKNOWN;
        }
        return state;
    }

    private static int getNextSubIdForState(IccCardConstants.State state, Context context) {
        SubscriptionManager subscriptionManager = SubscriptionManager.from(context);
        List<SubscriptionInfo> list = subscriptionManager.getActiveSubscriptionInfoList();
        if (list == null) {
            // getActiveSubscriptionInfoList was null callers expect an empty list.
            list = new ArrayList<>();
        }
        int resultId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
        int bestSlotId = Integer.MAX_VALUE; // Favor lowest slot first
        for (int i = 0; i < list.size(); i++) {
            final SubscriptionInfo info = list.get(i);
            final int id = info.getSubscriptionId();
            if (state == getSimState(info.getSimSlotIndex(), context)
                    && bestSlotId > info.getSimSlotIndex()) {
                resultId = id;
                bestSlotId = info.getSimSlotIndex();
            }
        }
        return resultId;
    }

    static private boolean handlePinEntry(Context context, String input,
                                          Activity pukInputActivity) {
        // TODO: The string constants here should be removed in favor
        // of some call to a static the MmiCode class that determines
        // if a dialstring is an MMI code.
        if ((input.startsWith("**04") || input.startsWith("**05"))
                && input.endsWith("#")) {
            UserManager userManager = (UserManager) pukInputActivity
                       .getSystemService(Context.USER_SERVICE);
            if (userManager.isSystemUser()) {
                PhoneGlobals app = PhoneGlobals.getInstance();
                Phone phone;
                int subId;
                if (input.startsWith("**04")) {
                    subId = getNextSubIdForState(IccCardConstants.State.PIN_REQUIRED, context);
                } else {
                    subId = getNextSubIdForState(IccCardConstants.State.PUK_REQUIRED, context);
                }
                if (SubscriptionManager.isValidSubscriptionId(subId)) {
                    log("get phone with subId: " + subId);
                    phone = PhoneGlobals.getPhone(subId);
                } else {
                    log("get default phone");
                    phone = PhoneGlobals.getPhone();
                }
                boolean isMMIHandled = phone.handlePinMmi(input);

                // if the PUK code is recognized then indicate to the
                // phone app that an attempt to unPUK the device was
                // made with this activity.  The PUK code may still
                // fail though, but we won't know until the MMI code
                // returns a result.
                if (isMMIHandled && input.startsWith("**05")) {
                    app.setPukEntryActivity(pukInputActivity);
                }
                return isMMIHandled;
            } else {
                AlertDialog dialog = new AlertDialog.Builder(context)
                        .setMessage(R.string.pin_puk_system_user_only)
                        .setPositiveButton(R.string.ok, null)
                        .setCancelable(true).create();
                dialog.show();
                dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
                dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
                return true;
            }
        }
        return false;
    }

    static private boolean handleIMEIDisplay(Context context,
                                             String input) {
        if (input.equals(MMI_IMEI_DISPLAY)) {
            showDeviceIdPanel(context);
            return true;
        }

        return false;
    }

    static private void showDeviceIdPanel(Context context) {
        if (DBG) log("showDeviceIdPanel()...");

        Phone phone = PhoneGlobals.getPhone();
        int labelId = TelephonyCapabilities.getDeviceIdLabel(phone);
        String deviceId = phone.getDeviceId();

        AlertDialog alert = new AlertDialog.Builder(context)
                .setTitle(labelId)
                .setMessage(deviceId)
                .setPositiveButton(R.string.ok, null)
                .setCancelable(false)
                .create();
        alert.getWindow().setType(WindowManager.LayoutParams.TYPE_PRIORITY_PHONE);
        alert.show();
    }

    private static boolean handleRegulatoryInfoDisplay(Context context, String input) {
        if (input.equals(MMI_REGULATORY_INFO_DISPLAY)) {
            log("handleRegulatoryInfoDisplay() sending intent to settings app");
            Intent showRegInfoIntent = new Intent(Settings.ACTION_SHOW_REGULATORY_INFO);
            try {
                context.startActivity(showRegInfoIntent);
            } catch (ActivityNotFoundException e) {
                Log.e(TAG, "startActivity() failed: " + e);
            }
            return true;
        }
        return false;
    }

    private static void log(String msg) {
        Log.d(TAG, "[SpecialCharSequenceMgr] " + msg);
    }
}
