/*
 * 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.provider.Settings;
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.getResources().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);
    }

}
