/*
 * Copyright (C) 2008 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.internal.location;

import java.io.UnsupportedEncodingException;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.LocationManager;
import android.location.INetInitiatedListener;
import android.telephony.TelephonyManager;
import android.telephony.PhoneNumberUtils;
import android.telephony.PhoneStateListener;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.SystemProperties;
import android.util.Log;

import com.android.internal.R;
import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.TelephonyProperties;

/**
 * A GPS Network-initiated Handler class used by LocationManager.
 *
 * {@hide}
 */
public class GpsNetInitiatedHandler {

    private static final String TAG = "GpsNetInitiatedHandler";

    private static final boolean DEBUG = true;
    private static final boolean VERBOSE = false;

    // NI verify activity for bringing up UI (not used yet)
    public static final String ACTION_NI_VERIFY = "android.intent.action.NETWORK_INITIATED_VERIFY";

    // string constants for defining data fields in NI Intent
    public static final String NI_INTENT_KEY_NOTIF_ID = "notif_id";
    public static final String NI_INTENT_KEY_TITLE = "title";
    public static final String NI_INTENT_KEY_MESSAGE = "message";
    public static final String NI_INTENT_KEY_TIMEOUT = "timeout";
    public static final String NI_INTENT_KEY_DEFAULT_RESPONSE = "default_resp";

    // the extra command to send NI response to GpsLocationProvider
    public static final String NI_RESPONSE_EXTRA_CMD = "send_ni_response";

    // the extra command parameter names in the Bundle
    public static final String NI_EXTRA_CMD_NOTIF_ID = "notif_id";
    public static final String NI_EXTRA_CMD_RESPONSE = "response";

    // these need to match GpsNiType constants in gps_ni.h
    public static final int GPS_NI_TYPE_VOICE = 1;
    public static final int GPS_NI_TYPE_UMTS_SUPL = 2;
    public static final int GPS_NI_TYPE_UMTS_CTRL_PLANE = 3;
    public static final int GPS_NI_TYPE_EMERGENCY_SUPL = 4;

    // these need to match GpsUserResponseType constants in gps_ni.h
    public static final int GPS_NI_RESPONSE_ACCEPT = 1;
    public static final int GPS_NI_RESPONSE_DENY = 2;
    public static final int GPS_NI_RESPONSE_NORESP = 3;
    public static final int GPS_NI_RESPONSE_IGNORE = 4;

    // these need to match GpsNiNotifyFlags constants in gps_ni.h
    public static final int GPS_NI_NEED_NOTIFY = 0x0001;
    public static final int GPS_NI_NEED_VERIFY = 0x0002;
    public static final int GPS_NI_PRIVACY_OVERRIDE = 0x0004;

    // these need to match GpsNiEncodingType in gps_ni.h
    public static final int GPS_ENC_NONE = 0;
    public static final int GPS_ENC_SUPL_GSM_DEFAULT = 1;
    public static final int GPS_ENC_SUPL_UTF8 = 2;
    public static final int GPS_ENC_SUPL_UCS2 = 3;
    public static final int GPS_ENC_UNKNOWN = -1;

    private final Context mContext;
    private final TelephonyManager mTelephonyManager;
    private final PhoneStateListener mPhoneStateListener;

    // parent gps location provider
    private final LocationManager mLocationManager;

    // configuration of notificaiton behavior
    private boolean mPlaySounds = false;
    private boolean mPopupImmediately = true;

    // read the SUPL_ES form gps.conf
    private volatile boolean mIsSuplEsEnabled;

    // Set to true if the phone is having emergency call.
    private volatile boolean mIsInEmergency;

    // If Location function is enabled.
    private volatile boolean mIsLocationEnabled = false;

    private final INetInitiatedListener mNetInitiatedListener;

    // Set to true if string from HAL is encoded as Hex, e.g., "3F0039"
    static private boolean mIsHexInput = true;

    public static class GpsNiNotification
    {
        public int notificationId;
        public int niType;
        public boolean needNotify;
        public boolean needVerify;
        public boolean privacyOverride;
        public int timeout;
        public int defaultResponse;
        public String requestorId;
        public String text;
        public int requestorIdEncoding;
        public int textEncoding;
        public Bundle extras;
    };

    public static class GpsNiResponse {
        /* User response, one of the values in GpsUserResponseType */
        int userResponse;
        /* Optional extra data to pass with the user response */
        Bundle extras;
    };

    private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {

        @Override public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
                String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
                /*
                   Emergency Mode is when during emergency call or in emergency call back mode.
                   For checking if it is during emergency call:
                       mIsInEmergency records if the phone is in emergency call or not. It will
                       be set to true when the phone is having emergency call, and then will
                       be set to false by mPhoneStateListener when the emergency call ends.
                   For checking if it is in emergency call back mode:
                       Emergency call back mode will be checked by reading system properties
                       when necessary: SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE)
                */
                setInEmergency(PhoneNumberUtils.isEmergencyNumber(phoneNumber));
                if (DEBUG) Log.v(TAG, "ACTION_NEW_OUTGOING_CALL - " + getInEmergency());
            } else if (action.equals(LocationManager.MODE_CHANGED_ACTION)) {
                updateLocationMode();
                if (DEBUG) Log.d(TAG, "location enabled :" + getLocationEnabled());
            }
        }
    };

    /**
     * The notification that is shown when a network-initiated notification
     * (and verification) event is received.
     * <p>
     * This is lazily created, so use {@link #setNINotification()}.
     */
    private Notification mNiNotification;

    public GpsNetInitiatedHandler(Context context,
                                  INetInitiatedListener netInitiatedListener,
                                  boolean isSuplEsEnabled) {
        mContext = context;

        if (netInitiatedListener == null) {
            throw new IllegalArgumentException("netInitiatedListener is null");
        } else {
            mNetInitiatedListener = netInitiatedListener;
        }

        setSuplEsEnabled(isSuplEsEnabled);
        mLocationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
        updateLocationMode();
        mTelephonyManager =
            (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);

        mPhoneStateListener = new PhoneStateListener() {
            @Override
            public void onCallStateChanged(int state, String incomingNumber) {
                if (DEBUG) Log.d(TAG, "onCallStateChanged(): state is "+ state);
                // listening for emergency call ends
                if (state == TelephonyManager.CALL_STATE_IDLE) {
                    setInEmergency(false);
                }
            }
        };
        mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_NEW_OUTGOING_CALL);
        intentFilter.addAction(LocationManager.MODE_CHANGED_ACTION);
        mContext.registerReceiver(mBroadcastReciever, intentFilter);
    }

    public void setSuplEsEnabled(boolean isEnabled) {
        mIsSuplEsEnabled = isEnabled;
    }

    public boolean getSuplEsEnabled() {
        return mIsSuplEsEnabled;
    }

    /**
     * Updates Location enabler based on location setting.
     */
    public void updateLocationMode() {
        mIsLocationEnabled = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    }

    /**
     * Checks if user agreed to use location.
     */
    public boolean getLocationEnabled() {
        return mIsLocationEnabled;
    }

    // Note: Currently, there are two mechanisms involved to determine if a
    // phone is in emergency mode:
    // 1. If the user is making an emergency call, this is provided by activly
    //    monitoring the outgoing phone number;
    // 2. If the device is in a emergency callback state, this is provided by
    //    system properties.
    // If either one of above exists, the phone is considered in an emergency
    // mode. Because of this complexity, we need to be careful about how to set
    // and clear the emergency state.
    public void setInEmergency(boolean isInEmergency) {
        mIsInEmergency = isInEmergency;
    }

    public boolean getInEmergency() {
        boolean isInEmergencyCallback = Boolean.parseBoolean(
                SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE));
        return mIsInEmergency || isInEmergencyCallback;
    }


    // Handles NI events from HAL
    public void handleNiNotification(GpsNiNotification notif) {
        if (DEBUG) Log.d(TAG, "in handleNiNotification () :"
                        + " notificationId: " + notif.notificationId
                        + " requestorId: " + notif.requestorId
                        + " text: " + notif.text
                        + " mIsSuplEsEnabled" + getSuplEsEnabled()
                        + " mIsLocationEnabled" + getLocationEnabled());

        if (getSuplEsEnabled()) {
            handleNiInEs(notif);
        } else {
            handleNi(notif);
        }

        //////////////////////////////////////////////////////////////////////////
        //   A note about timeout
        //   According to the protocol, in the need_notify and need_verify case,
        //   a default response should be sent when time out.
        //
        //   In some GPS hardware, the GPS driver (under HAL) can handle the timeout case
        //   and this class GpsNetInitiatedHandler does not need to do anything.
        //
        //   However, the UI should at least close the dialog when timeout. Further,
        //   for more general handling, timeout response should be added to the Handler here.
        //
    }

    // handle NI form HAL when SUPL_ES is disabled.
    private void handleNi(GpsNiNotification notif) {
        if (DEBUG) Log.d(TAG, "in handleNi () :"
                        + " needNotify: " + notif.needNotify
                        + " needVerify: " + notif.needVerify
                        + " privacyOverride: " + notif.privacyOverride
                        + " mPopupImmediately: " + mPopupImmediately
                        + " mInEmergency: " + getInEmergency());

        if (!getLocationEnabled() && !getInEmergency()) {
            // Location is currently disabled, ignore all NI requests.
            try {
                mNetInitiatedListener.sendNiResponse(notif.notificationId,
                                                     GPS_NI_RESPONSE_IGNORE);
            } catch (RemoteException e) {
                Log.e(TAG, "RemoteException in sendNiResponse");
            }
        }
        if (notif.needNotify) {
        // If NI does not need verify or the dialog is not requested
        // to pop up immediately, the dialog box will not pop up.
            if (notif.needVerify && mPopupImmediately) {
                // Popup the dialog box now
                openNiDialog(notif);
            } else {
                // Show the notification
                setNiNotification(notif);
            }
        }
        // ACCEPT cases: 1. Notify, no verify; 2. no notify, no verify;
        // 3. privacy override.
        if (!notif.needVerify || notif.privacyOverride) {
            try {
                mNetInitiatedListener.sendNiResponse(notif.notificationId,
                                                     GPS_NI_RESPONSE_ACCEPT);
            } catch (RemoteException e) {
                Log.e(TAG, "RemoteException in sendNiResponse");
            }
        }
    }

    // handle NI from HAL when the SUPL_ES is enabled
    private void handleNiInEs(GpsNiNotification notif) {

        if (DEBUG) Log.d(TAG, "in handleNiInEs () :"
                    + " niType: " + notif.niType
                    + " notificationId: " + notif.notificationId);

        // UE is in emergency mode when in emergency call mode or in emergency call back mode
        /*
           1. When SUPL ES bit is off and UE is not in emergency mode:
                  Call handleNi() to do legacy behaviour.
           2. When SUPL ES bit is on and UE is in emergency mode:
                  Call handleNi() to do acceptance behaviour.
           3. When SUPL ES bit is off but UE is in emergency mode:
                  Ignore the emergency SUPL INIT.
           4. When SUPL ES bit is on but UE is not in emergency mode:
                  Ignore the emergency SUPL INIT.
        */
        boolean isNiTypeES = (notif.niType == GPS_NI_TYPE_EMERGENCY_SUPL);
        if (isNiTypeES != getInEmergency()) {
            try {
                mNetInitiatedListener.sendNiResponse(notif.notificationId,
                                                     GPS_NI_RESPONSE_IGNORE);
            } catch (RemoteException e) {
                Log.e(TAG, "RemoteException in sendNiResponse");
            }
        } else {
            handleNi(notif);
        }
    }

    // Sets the NI notification.
    private synchronized void setNiNotification(GpsNiNotification notif) {
        NotificationManager notificationManager = (NotificationManager) mContext
                .getSystemService(Context.NOTIFICATION_SERVICE);
        if (notificationManager == null) {
            return;
        }

        String title = getNotifTitle(notif, mContext);
        String message = getNotifMessage(notif, mContext);

        if (DEBUG) Log.d(TAG, "setNiNotification, notifyId: " + notif.notificationId +
                ", title: " + title +
                ", message: " + message);

        // Construct Notification
        if (mNiNotification == null) {
            mNiNotification = new Notification();
            mNiNotification.icon = com.android.internal.R.drawable.stat_sys_gps_on; /* Change notification icon here */
            mNiNotification.when = 0;
        }

        if (mPlaySounds) {
            mNiNotification.defaults |= Notification.DEFAULT_SOUND;
        } else {
            mNiNotification.defaults &= ~Notification.DEFAULT_SOUND;
        }

        mNiNotification.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_AUTO_CANCEL;
        mNiNotification.tickerText = getNotifTicker(notif, mContext);

        // if not to popup dialog immediately, pending intent will open the dialog
        Intent intent = !mPopupImmediately ? getDlgIntent(notif) : new Intent();
        PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, intent, 0);
        mNiNotification.color = mContext.getColor(
                com.android.internal.R.color.system_notification_accent_color);
        mNiNotification.setLatestEventInfo(mContext, title, message, pi);

        notificationManager.notifyAsUser(null, notif.notificationId, mNiNotification,
                UserHandle.ALL);
    }

    // Opens the notification dialog and waits for user input
    private void openNiDialog(GpsNiNotification notif)
    {
        Intent intent = getDlgIntent(notif);

        if (DEBUG) Log.d(TAG, "openNiDialog, notifyId: " + notif.notificationId +
                ", requestorId: " + notif.requestorId +
                ", text: " + notif.text);

        mContext.startActivity(intent);
    }

    // Construct the intent for bringing up the dialog activity, which shows the
    // notification and takes user input
    private Intent getDlgIntent(GpsNiNotification notif)
    {
        Intent intent = new Intent();
        String title = getDialogTitle(notif, mContext);
        String message = getDialogMessage(notif, mContext);

        // directly bring up the NI activity
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        intent.setClass(mContext, com.android.internal.app.NetInitiatedActivity.class);

        // put data in the intent
        intent.putExtra(NI_INTENT_KEY_NOTIF_ID, notif.notificationId);
        intent.putExtra(NI_INTENT_KEY_TITLE, title);
        intent.putExtra(NI_INTENT_KEY_MESSAGE, message);
        intent.putExtra(NI_INTENT_KEY_TIMEOUT, notif.timeout);
        intent.putExtra(NI_INTENT_KEY_DEFAULT_RESPONSE, notif.defaultResponse);

        if (DEBUG) Log.d(TAG, "generateIntent, title: " + title + ", message: " + message +
                ", timeout: " + notif.timeout);

        return intent;
    }

    // Converts a string (or Hex string) to a char array
    static byte[] stringToByteArray(String original, boolean isHex)
    {
        int length = isHex ? original.length() / 2 : original.length();
        byte[] output = new byte[length];
        int i;

        if (isHex)
        {
            for (i = 0; i < length; i++)
            {
                output[i] = (byte) Integer.parseInt(original.substring(i*2, i*2+2), 16);
            }
        }
        else {
            for (i = 0; i < length; i++)
            {
                output[i] = (byte) original.charAt(i);
            }
        }

        return output;
    }

    /**
     * Unpacks an byte array containing 7-bit packed characters into a String.
     *
     * @param input a 7-bit packed char array
     * @return the unpacked String
     */
    static String decodeGSMPackedString(byte[] input)
    {
        final char PADDING_CHAR = 0x00;
        int lengthBytes = input.length;
        int lengthSeptets = (lengthBytes * 8) / 7;
        String decoded;

        /* Special case where the last 7 bits in the last byte could hold a valid
         * 7-bit character or a padding character. Drop the last 7-bit character
         * if it is a padding character.
         */
        if (lengthBytes % 7 == 0) {
            if (lengthBytes > 0) {
                if ((input[lengthBytes - 1] >> 1) == PADDING_CHAR) {
                    lengthSeptets = lengthSeptets - 1;
                }
            }
        }

        decoded = GsmAlphabet.gsm7BitPackedToString(input, 0, lengthSeptets);

        // Return "" if decoding of GSM packed string fails
        if (null == decoded) {
            Log.e(TAG, "Decoding of GSM packed string failed");
            decoded = "";
        }

        return decoded;
    }

    static String decodeUTF8String(byte[] input)
    {
        String decoded = "";
        try {
            decoded = new String(input, "UTF-8");
        }
        catch (UnsupportedEncodingException e)
        {
            throw new AssertionError();
        }
        return decoded;
    }

    static String decodeUCS2String(byte[] input)
    {
        String decoded = "";
        try {
            decoded = new String(input, "UTF-16");
        }
        catch (UnsupportedEncodingException e)
        {
            throw new AssertionError();
        }
        return decoded;
    }

    /** Decode NI string
     *
     * @param original   The text string to be decoded
     * @param isHex      Specifies whether the content of the string has been encoded as a Hex string. Encoding
     *                   a string as Hex can allow zeros inside the coded text.
     * @param coding     Specifies the coding scheme of the string, such as GSM, UTF8, UCS2, etc. This coding scheme
     *                      needs to match those used passed to HAL from the native GPS driver. Decoding is done according
     *                   to the <code> coding </code>, after a Hex string is decoded. Generally, if the
     *                   notification strings don't need further decoding, <code> coding </code> encoding can be
     *                   set to -1, and <code> isHex </code> can be false.
     * @return the decoded string
     */
    static private String decodeString(String original, boolean isHex, int coding)
    {
        String decoded = original;
        byte[] input = stringToByteArray(original, isHex);

        switch (coding) {
        case GPS_ENC_NONE:
            decoded = original;
            break;

        case GPS_ENC_SUPL_GSM_DEFAULT:
            decoded = decodeGSMPackedString(input);
            break;

        case GPS_ENC_SUPL_UTF8:
            decoded = decodeUTF8String(input);
            break;

        case GPS_ENC_SUPL_UCS2:
            decoded = decodeUCS2String(input);
            break;

        case GPS_ENC_UNKNOWN:
            decoded = original;
            break;

        default:
            Log.e(TAG, "Unknown encoding " + coding + " for NI text " + original);
            break;
        }
        return decoded;
    }

    // change this to configure notification display
    static private String getNotifTicker(GpsNiNotification notif, Context context)
    {
        String ticker = String.format(context.getString(R.string.gpsNotifTicker),
                decodeString(notif.requestorId, mIsHexInput, notif.requestorIdEncoding),
                decodeString(notif.text, mIsHexInput, notif.textEncoding));
        return ticker;
    }

    // change this to configure notification display
    static private String getNotifTitle(GpsNiNotification notif, Context context)
    {
        String title = String.format(context.getString(R.string.gpsNotifTitle));
        return title;
    }

    // change this to configure notification display
    static private String getNotifMessage(GpsNiNotification notif, Context context)
    {
        String message = String.format(context.getString(R.string.gpsNotifMessage),
                decodeString(notif.requestorId, mIsHexInput, notif.requestorIdEncoding),
                decodeString(notif.text, mIsHexInput, notif.textEncoding));
        return message;
    }

    // change this to configure dialog display (for verification)
    static public String getDialogTitle(GpsNiNotification notif, Context context)
    {
        return getNotifTitle(notif, context);
    }

    // change this to configure dialog display (for verification)
    static private String getDialogMessage(GpsNiNotification notif, Context context)
    {
        return getNotifMessage(notif, context);
    }

}
