/*
 * Copyright (C) 2015 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 android.support.v7.mms;

import android.content.Context;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.Proxy;
import java.net.URL;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * MMS HTTP client for sending and downloading MMS messages
 */
public class MmsHttpClient {
    static final String METHOD_POST = "POST";
    static final String METHOD_GET = "GET";

    private static final String HEADER_CONTENT_TYPE = "Content-Type";
    private static final String HEADER_ACCEPT = "Accept";
    private static final String HEADER_ACCEPT_LANGUAGE = "Accept-Language";
    private static final String HEADER_USER_AGENT = "User-Agent";

    // The "Accept" header value
    private static final String HEADER_VALUE_ACCEPT =
            "*/*, application/vnd.wap.mms-message, application/vnd.wap.sic";
    // The "Content-Type" header value
    private static final String HEADER_VALUE_CONTENT_TYPE_WITH_CHARSET =
            "application/vnd.wap.mms-message; charset=utf-8";
    private static final String HEADER_VALUE_CONTENT_TYPE_WITHOUT_CHARSET =
            "application/vnd.wap.mms-message";

    /*
     * Macro names
     */
    // The raw phone number
    private static final String MACRO_LINE1 = "LINE1";
    // The phone number without country code
    private static final String MACRO_LINE1NOCOUNTRYCODE = "LINE1NOCOUNTRYCODE";
    // NAI (Network Access Identifier)
    private static final String MACRO_NAI = "NAI";

    // The possible NAI system property name
    private static final String NAI_PROPERTY = "persist.radio.cdma.nai";

    private final Context mContext;
    private final TelephonyManager mTelephonyManager;

    /**
     * Constructor
     *
     * @param context The Context object
     */
    MmsHttpClient(Context context) {
        mContext = context;
        mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    }

    /**
     * Execute an MMS HTTP request, either a POST (sending) or a GET (downloading)
     *
     * @param urlString The request URL, for sending it is usually the MMSC, and for downloading
     *                  it is the message URL
     * @param pdu For POST (sending) only, the PDU to send
     * @param method HTTP method, POST for sending and GET for downloading
     * @param isProxySet Is there a proxy for the MMSC
     * @param proxyHost The proxy host
     * @param proxyPort The proxy port
     * @param mmsConfig The MMS config to use
     * @param userAgent The user agent header value
     * @param uaProfUrl The UA Prof URL header value
     * @return The HTTP response body
     * @throws MmsHttpException For any failures
     */
    public byte[] execute(String urlString, byte[] pdu, String method, boolean isProxySet,
            String proxyHost, int proxyPort, Bundle mmsConfig, String userAgent, String uaProfUrl)
            throws MmsHttpException {
        Log.d(MmsService.TAG, "HTTP: " + method + " " + Utils.redactUrlForNonVerbose(urlString)
                + (isProxySet ? (", proxy=" + proxyHost + ":" + proxyPort) : "")
                + ", PDU size=" + (pdu != null ? pdu.length : 0));
        checkMethod(method);
        HttpURLConnection connection = null;
        try {
            Proxy proxy = Proxy.NO_PROXY;
            if (isProxySet) {
                proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
            }
            final URL url = new URL(urlString);
            // Now get the connection
            connection = (HttpURLConnection) url.openConnection(proxy);
            connection.setDoInput(true);
            connection.setConnectTimeout(
                    mmsConfig.getInt(CarrierConfigValuesLoader.CONFIG_HTTP_SOCKET_TIMEOUT,
                            CarrierConfigValuesLoader.CONFIG_HTTP_SOCKET_TIMEOUT_DEFAULT));
            // ------- COMMON HEADERS ---------
            // Header: Accept
            connection.setRequestProperty(HEADER_ACCEPT, HEADER_VALUE_ACCEPT);
            // Header: Accept-Language
            connection.setRequestProperty(
                    HEADER_ACCEPT_LANGUAGE, getCurrentAcceptLanguage(Locale.getDefault()));
            // Header: User-Agent
            Log.i(MmsService.TAG, "HTTP: User-Agent=" + userAgent);
            connection.setRequestProperty(HEADER_USER_AGENT, userAgent);
            // Header: x-wap-profile
            final String uaProfUrlTagName = mmsConfig.getString(
                    CarrierConfigValuesLoader.CONFIG_UA_PROF_TAG_NAME,
                    CarrierConfigValuesLoader.CONFIG_UA_PROF_TAG_NAME_DEFAULT);
            if (uaProfUrl != null) {
                Log.i(MmsService.TAG, "HTTP: UaProfUrl=" + uaProfUrl);
                connection.setRequestProperty(uaProfUrlTagName, uaProfUrl);
            }
            // Add extra headers specified by mms_config.xml's httpparams
            addExtraHeaders(connection, mmsConfig);
            // Different stuff for GET and POST
            if (METHOD_POST.equals(method)) {
                if (pdu == null || pdu.length < 1) {
                    Log.e(MmsService.TAG, "HTTP: empty pdu");
                    throw new MmsHttpException(0/*statusCode*/, "Sending empty PDU");
                }
                connection.setDoOutput(true);
                connection.setRequestMethod(METHOD_POST);
                if (mmsConfig.getBoolean(
                        CarrierConfigValuesLoader.CONFIG_SUPPORT_HTTP_CHARSET_HEADER,
                        CarrierConfigValuesLoader.CONFIG_SUPPORT_HTTP_CHARSET_HEADER_DEFAULT)) {
                    connection.setRequestProperty(HEADER_CONTENT_TYPE,
                            HEADER_VALUE_CONTENT_TYPE_WITH_CHARSET);
                } else {
                    connection.setRequestProperty(HEADER_CONTENT_TYPE,
                            HEADER_VALUE_CONTENT_TYPE_WITHOUT_CHARSET);
                }
                if (Log.isLoggable(MmsService.TAG, Log.VERBOSE)) {
                    logHttpHeaders(connection.getRequestProperties());
                }
                connection.setFixedLengthStreamingMode(pdu.length);
                // Sending request body
                final OutputStream out =
                        new BufferedOutputStream(connection.getOutputStream());
                out.write(pdu);
                out.flush();
                out.close();
            } else if (METHOD_GET.equals(method)) {
                if (Log.isLoggable(MmsService.TAG, Log.VERBOSE)) {
                    logHttpHeaders(connection.getRequestProperties());
                }
                connection.setRequestMethod(METHOD_GET);
            }
            // Get response
            final int responseCode = connection.getResponseCode();
            final String responseMessage = connection.getResponseMessage();
            Log.d(MmsService.TAG, "HTTP: " + responseCode + " " + responseMessage);
            if (Log.isLoggable(MmsService.TAG, Log.VERBOSE)) {
                logHttpHeaders(connection.getHeaderFields());
            }
            if (responseCode / 100 != 2) {
                throw new MmsHttpException(responseCode, responseMessage);
            }
            final InputStream in = new BufferedInputStream(connection.getInputStream());
            final ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
            final byte[] buf = new byte[4096];
            int count = 0;
            while ((count = in.read(buf)) > 0) {
                byteOut.write(buf, 0, count);
            }
            in.close();
            final byte[] responseBody = byteOut.toByteArray();
            Log.d(MmsService.TAG, "HTTP: response size="
                    + (responseBody != null ? responseBody.length : 0));
            return responseBody;
        } catch (MalformedURLException e) {
            final String redactedUrl = Utils.redactUrlForNonVerbose(urlString);
            Log.e(MmsService.TAG, "HTTP: invalid URL " + redactedUrl, e);
            throw new MmsHttpException(0/*statusCode*/, "Invalid URL " + redactedUrl, e);
        } catch (ProtocolException e) {
            final String redactedUrl = Utils.redactUrlForNonVerbose(urlString);
            Log.e(MmsService.TAG, "HTTP: invalid URL protocol " + redactedUrl, e);
            throw new MmsHttpException(0/*statusCode*/, "Invalid URL protocol " + redactedUrl, e);
        } catch (IOException e) {
            Log.e(MmsService.TAG, "HTTP: IO failure", e);
            throw new MmsHttpException(0/*statusCode*/, e);
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }

    private static void logHttpHeaders(Map<String, List<String>> headers) {
        final StringBuilder sb = new StringBuilder();
        if (headers != null) {
            for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
                final String key = entry.getKey();
                final List<String> values = entry.getValue();
                if (values != null) {
                    for (String value : values) {
                        sb.append(key).append('=').append(value).append('\n');
                    }
                }
            }
            Log.v(MmsService.TAG, "HTTP: headers\n" + sb.toString());
        }
    }

    private static void checkMethod(String method) throws MmsHttpException {
        if (!METHOD_GET.equals(method) && !METHOD_POST.equals(method)) {
            throw new MmsHttpException(0/*statusCode*/, "Invalid method " + method);
        }
    }

    private static final String ACCEPT_LANG_FOR_US_LOCALE = "en-US";

    /**
     * Return the Accept-Language header.  Use the current locale plus
     * US if we are in a different locale than US.
     * This code copied from the browser's WebSettings.java
     *
     * @return Current AcceptLanguage String.
     */
    public static String getCurrentAcceptLanguage(Locale locale) {
        final StringBuilder buffer = new StringBuilder();
        addLocaleToHttpAcceptLanguage(buffer, locale);

        if (!Locale.US.equals(locale)) {
            if (buffer.length() > 0) {
                buffer.append(", ");
            }
            buffer.append(ACCEPT_LANG_FOR_US_LOCALE);
        }

        return buffer.toString();
    }

    /**
     * Convert obsolete language codes, including Hebrew/Indonesian/Yiddish,
     * to new standard.
     */
    private static String convertObsoleteLanguageCodeToNew(String langCode) {
        if (langCode == null) {
            return null;
        }
        if ("iw".equals(langCode)) {
            // Hebrew
            return "he";
        } else if ("in".equals(langCode)) {
            // Indonesian
            return "id";
        } else if ("ji".equals(langCode)) {
            // Yiddish
            return "yi";
        }
        return langCode;
    }

    private static void addLocaleToHttpAcceptLanguage(StringBuilder builder, Locale locale) {
        final String language = convertObsoleteLanguageCodeToNew(locale.getLanguage());
        if (language != null) {
            builder.append(language);
            final String country = locale.getCountry();
            if (country != null) {
                builder.append("-");
                builder.append(country);
            }
        }
    }

    private static final Pattern MACRO_P = Pattern.compile("##(\\S+)##");
    /**
     * Resolve the macro in HTTP param value text
     * For example, "something##LINE1##something" is resolved to "something9139531419something"
     *
     * @param value The HTTP param value possibly containing macros
     * @return The HTTP param with macro resolved to real value
     */
    private String resolveMacro(String value, Bundle mmsConfig) {
        if (TextUtils.isEmpty(value)) {
            return value;
        }
        final Matcher matcher = MACRO_P.matcher(value);
        int nextStart = 0;
        StringBuilder replaced = null;
        while (matcher.find()) {
            if (replaced == null) {
                replaced = new StringBuilder();
            }
            final int matchedStart = matcher.start();
            if (matchedStart > nextStart) {
                replaced.append(value.substring(nextStart, matchedStart));
            }
            final String macro = matcher.group(1);
            final String macroValue = getHttpParamMacro(macro, mmsConfig);
            if (macroValue != null) {
                replaced.append(macroValue);
            }
            nextStart = matcher.end();
        }
        if (replaced != null && nextStart < value.length()) {
            replaced.append(value.substring(nextStart));
        }
        return replaced == null ? value : replaced.toString();
    }

    /**
     * Add extra HTTP headers from mms_config.xml's httpParams, which is a list of key/value
     * pairs separated by "|". Each key/value pair is separated by ":". Value may contain
     * macros like "##LINE1##" or "##NAI##" which is resolved with methods in this class
     *
     * @param connection The HttpURLConnection that we add headers to
     * @param mmsConfig The MmsConfig object
     */
    private void addExtraHeaders(HttpURLConnection connection, Bundle mmsConfig) {
        final String extraHttpParams = mmsConfig.getString(
                CarrierConfigValuesLoader.CONFIG_HTTP_PARAMS);
        if (!TextUtils.isEmpty(extraHttpParams)) {
            // Parse the parameter list
            String paramList[] = extraHttpParams.split("\\|");
            for (String paramPair : paramList) {
                String splitPair[] = paramPair.split(":", 2);
                if (splitPair.length == 2) {
                    final String name = splitPair[0].trim();
                    final String value = resolveMacro(splitPair[1].trim(), mmsConfig);
                    if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(value)) {
                        // Add the header if the param is valid
                        connection.setRequestProperty(name, value);
                    }
                }
            }
        }
    }

    /**
     * Return the HTTP param macro value.
     * Example: LINE1 returns the phone number, etc.
     *
     * @param macro The macro name
     * @param mmsConfig The carrier configuration values
     * @return The value of the defined macro
     */
    private String getHttpParamMacro(final String macro, final Bundle mmsConfig) {
        if (MACRO_LINE1.equals(macro)) {
            return getSelfNumber();
        } else if (MACRO_LINE1NOCOUNTRYCODE.equals(macro)) {
            return PhoneNumberHelper.getNumberNoCountryCode(
                    getSelfNumber(), getSimOrLocaleCountry());
        }  else if (MACRO_NAI.equals(macro)) {
            return getEncodedNai(mmsConfig.getString(
                    CarrierConfigValuesLoader.CONFIG_NAI_SUFFIX,
                    CarrierConfigValuesLoader.CONFIG_NAI_SUFFIX_DEFAULT));
        }
        return null;
    }

    /**
     * Get the device phone number
     *
     * @return the phone number text
     */
    private String getSelfNumber() {
        if (Utils.supportMSim()) {
            final SubscriptionManager subscriptionManager = SubscriptionManager.from(mContext);
            final SubscriptionInfo info = subscriptionManager.getActiveSubscriptionInfo(
                    SmsManager.getDefaultSmsSubscriptionId());
            if (info != null) {
                return info.getNumber();
            } else {
                return null;
            }
        } else {
            return mTelephonyManager.getLine1Number();
        }
    }

    /**
     * Get the country ISO code from SIM or system locale
     *
     * @return the country ISO code
     */
    private String getSimOrLocaleCountry() {
        String country = null;
        if (Utils.supportMSim()) {
            final SubscriptionManager subscriptionManager = SubscriptionManager.from(mContext);
            final SubscriptionInfo info = subscriptionManager.getActiveSubscriptionInfo(
                    SmsManager.getDefaultSmsSubscriptionId());
            if (info != null) {
                country = info.getCountryIso();
            }
        } else {
            country = mTelephonyManager.getSimCountryIso();
        }
        if (!TextUtils.isEmpty(country)) {
            return country.toUpperCase();
        } else {
            return Locale.getDefault().getCountry();
        }
    }

    /**
     * Get encoded NAI string to use as the HTTP header for some carriers.
     * On L-MR1+, we call the hidden system API to get this
     * On L-MR1-, we try to find it via system property.
     *
     * @param naiSuffix the suffix to append to NAI before encoding
     * @return the Base64 encoded NAI string to use as HTTP header
     */
    private String getEncodedNai(final String naiSuffix) {
        String nai;
        if (Utils.supportMSim()) {
            nai = getNaiBySystemApi(
                    getSlotId(Utils.getEffectiveSubscriptionId(MmsManager.DEFAULT_SUB_ID)));
        } else {
            nai = getNaiBySystemProperty();
        }
        if (!TextUtils.isEmpty(nai)) {
            Log.i(MmsService.TAG, "NAI is not empty");
            if (!TextUtils.isEmpty(naiSuffix)) {
                nai = nai + naiSuffix;
            }
            byte[] encoded = null;
            try {
                encoded = Base64.encode(nai.getBytes("UTF-8"), Base64.NO_WRAP);
            } catch (UnsupportedEncodingException e) {
                encoded = Base64.encode(nai.getBytes(), Base64.NO_WRAP);
            }
            try {
                return new String(encoded, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                return new String(encoded);
            }
        }
        return null;
    }

    /**
     * Invoke hidden SubscriptionManager.getSlotId(int)
     *
     * @param subId the subId
     * @return the SIM slot ID
     */
    private static int getSlotId(final int subId) {
        try {
            final Method method = SubscriptionManager.class.getMethod("getSlotId", Integer.TYPE);
            if (method != null) {
                return (Integer) method.invoke(null, subId);
            }
        } catch (Exception e) {
            Log.w(MmsService.TAG, "SubscriptionManager.getSlotId failed " + e);
        }
        return -1;
    }

    /**
     * Get NAI using hidden TelephonyManager.getNai(int)
     *
     * @param slotId the SIM slot ID
     * @return the NAI string
     */
    private String getNaiBySystemApi(final int slotId) {
        try {
            final Method method = mTelephonyManager.getClass().getMethod("getNai", Integer.TYPE);
            if (method != null) {
                return (String) method.invoke(mTelephonyManager, slotId);
            }
        } catch (Exception e) {
            Log.w(MmsService.TAG, "TelephonyManager.getNai failed " + e);
        }
        return null;
    }

    /**
     * Get NAI using hidden SystemProperties.get(String)
     *
     * @return the NAI string as system property
     */
    private static String getNaiBySystemProperty() {
        try {
            final Class systemPropertiesClass = Class.forName("android.os.SystemProperties");
            if (systemPropertiesClass != null) {
                final Method method = systemPropertiesClass.getMethod("get", String.class);
                if (method != null) {
                    return (String) method.invoke(null, NAI_PROPERTY);
                }
            }
        } catch (Exception e) {
            Log.w(MmsService.TAG, "SystemProperties.get failed " + e);
        }
        return null;
    }
}
