/*
 * 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.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v7.mms.pdu.GenericPdu;
import android.support.v7.mms.pdu.PduHeaders;
import android.support.v7.mms.pdu.PduParser;
import android.support.v7.mms.pdu.SendConf;
import android.telephony.SmsManager;
import android.text.TextUtils;
import android.util.Log;

import java.lang.reflect.Method;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * MMS request base class. This handles the execution of any MMS request.
 */
abstract class MmsRequest implements Parcelable {
    /**
     * Prepare to make the HTTP request - will download message for sending
     *
     * @param context the Context
     * @param mmsConfig carrier config values to use
     * @return true if loading request PDU from calling app succeeds, false otherwise
     */
    protected abstract boolean loadRequest(Context context, Bundle mmsConfig);

    /**
     * Transfer the received response to the caller
     *
     * @param context the Context
     * @param fillIn the content of pending intent to be returned
     * @param response the pdu to transfer
     * @return true if transferring response PDU to calling app succeeds, false otherwise
     */
    protected abstract boolean transferResponse(Context context, Intent fillIn, byte[] response);

    /**
     * Making the HTTP request to MMSC
     *
     * @param context The context
     * @param netMgr The current {@link MmsNetworkManager}
     * @param apn The APN
     * @param mmsConfig The carrier configuration values to use
     * @param userAgent The User-Agent header value
     * @param uaProfUrl The UA Prof URL header value
     * @return The HTTP response data
     * @throws MmsHttpException If any network error happens
     */
    protected abstract byte[] doHttp(Context context, MmsNetworkManager netMgr,
            ApnSettingsLoader.Apn apn, Bundle mmsConfig, String userAgent, String uaProfUrl)
            throws MmsHttpException;

    /**
     * Get the HTTP request URL for this MMS request
     *
     * @param apn The APN to use
     * @return The HTTP request URL in text
     */
    protected abstract String getHttpRequestUrl(ApnSettingsLoader.Apn apn);

    // Maximum time to spend waiting to read data from a content provider before failing with error.
    protected static final int TASK_TIMEOUT_MS = 30 * 1000;

    protected final String mLocationUrl;
    protected final Uri mPduUri;
    protected final PendingIntent mPendingIntent;
    // Thread pool for transferring PDU with MMS apps
    protected final ExecutorService mPduTransferExecutor = Executors.newCachedThreadPool();

    // Whether this request should acquire wake lock
    private boolean mUseWakeLock;

    protected MmsRequest(final String locationUrl, final Uri pduUri,
            final PendingIntent pendingIntent) {
        mLocationUrl = locationUrl;
        mPduUri = pduUri;
        mPendingIntent = pendingIntent;
        mUseWakeLock = true;
    }

    void setUseWakeLock(final boolean useWakeLock) {
        mUseWakeLock = useWakeLock;
    }

    boolean getUseWakeLock() {
        return mUseWakeLock;
    }

    /**
     * Run the MMS request.
     *
     * @param context the context to use
     * @param networkManager the MmsNetworkManager to use to setup MMS network
     * @param apnSettingsLoader the APN loader
     * @param carrierConfigValuesLoader the carrier config loader
     * @param userAgentInfoLoader the user agent info loader
     */
    void execute(final Context context, final MmsNetworkManager networkManager,
            final ApnSettingsLoader apnSettingsLoader,
            final CarrierConfigValuesLoader carrierConfigValuesLoader,
            final UserAgentInfoLoader userAgentInfoLoader) {
        Log.i(MmsService.TAG, "Execute " + this.getClass().getSimpleName());
        int result = SmsManager.MMS_ERROR_UNSPECIFIED;
        int httpStatusCode = 0;
        byte[] response = null;
        final Bundle mmsConfig = carrierConfigValuesLoader.get(MmsManager.DEFAULT_SUB_ID);
        if (mmsConfig == null) {
            Log.e(MmsService.TAG, "Failed to load carrier configuration values");
            result = SmsManager.MMS_ERROR_CONFIGURATION_ERROR;
        } else if (!loadRequest(context, mmsConfig)) {
            Log.e(MmsService.TAG, "Failed to load PDU");
            result = SmsManager.MMS_ERROR_IO_ERROR;
        } else {
            // Everything's OK. Now execute the request.
            try {
                // Acquire the MMS network
                networkManager.acquireNetwork();
                // Load the potential APNs. In most cases there should be only one APN available.
                // On some devices on which we can't obtain APN from system, we look up our own
                // APN list. Since we don't have exact information, we may get a list of potential
                // APNs to try. Whenever we found a successful APN, we signal it and return.
                final String apnName = networkManager.getApnName();
                final List<ApnSettingsLoader.Apn> apns = apnSettingsLoader.get(apnName);
                if (apns.size() < 1) {
                    throw new ApnException("No valid APN");
                } else {
                    Log.d(MmsService.TAG, "Trying " + apns.size() + " APNs");
                }
                final String userAgent = userAgentInfoLoader.getUserAgent();
                final String uaProfUrl = userAgentInfoLoader.getUAProfUrl();
                MmsHttpException lastException = null;
                for (ApnSettingsLoader.Apn apn : apns) {
                    Log.i(MmsService.TAG, "Using APN ["
                            + "MMSC=" + apn.getMmsc() + ", "
                            + "PROXY=" + apn.getMmsProxy() + ", "
                            + "PORT=" + apn.getMmsProxyPort() + "]");
                    try {
                        final String url = getHttpRequestUrl(apn);
                        // Request a global route for the host to connect
                        requestRoute(networkManager.getConnectivityManager(), apn, url);
                        // Perform the HTTP request
                        response = doHttp(
                                context, networkManager, apn, mmsConfig, userAgent, uaProfUrl);
                        // Additional check of whether this is a success
                        if (isWrongApnResponse(response, mmsConfig)) {
                            throw new MmsHttpException(0/*statusCode*/, "Invalid sending address");
                        }
                        // Notify APN loader this is a valid APN
                        apn.setSuccess();
                        result = Activity.RESULT_OK;
                        break;
                    } catch (MmsHttpException e) {
                        Log.w(MmsService.TAG, "HTTP or network failure", e);
                        lastException = e;
                    }
                }
                if (lastException != null) {
                    throw lastException;
                }
            } catch (ApnException e) {
                Log.e(MmsService.TAG, "MmsRequest: APN failure", e);
                result = SmsManager.MMS_ERROR_INVALID_APN;
            } catch (MmsNetworkException e) {
                Log.e(MmsService.TAG, "MmsRequest: MMS network acquiring failure", e);
                result = SmsManager.MMS_ERROR_UNABLE_CONNECT_MMS;
            } catch (MmsHttpException e) {
                Log.e(MmsService.TAG, "MmsRequest: HTTP or network I/O failure", e);
                result = SmsManager.MMS_ERROR_HTTP_FAILURE;
                httpStatusCode = e.getStatusCode();
            } catch (Exception e) {
                Log.e(MmsService.TAG, "MmsRequest: unexpected failure", e);
                result = SmsManager.MMS_ERROR_UNSPECIFIED;
            } finally {
                // Release MMS network
                networkManager.releaseNetwork();
            }
        }
        // Process result and send back via PendingIntent
        returnResult(context, result, response, httpStatusCode);
    }

    /**
     * Check if the response indicates a failure when we send to wrong APN.
     * Sometimes even if you send to the wrong APN, a response in valid PDU format can still
     * be sent back but with an error status. Check one specific case here.
     *
     * TODO: maybe there are other possibilities.
     *
     * @param response the response data
     * @param mmsConfig the carrier configuration values to use
     * @return false if we find an invalid response case, otherwise true
     */
    static boolean isWrongApnResponse(final byte[] response, final Bundle mmsConfig) {
        if (response != null && response.length > 0) {
            try {
                final GenericPdu pdu = new PduParser(
                        response,
                        mmsConfig.getBoolean(
                                CarrierConfigValuesLoader
                                        .CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION,
                                CarrierConfigValuesLoader
                                        .CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION_DEFAULT))
                        .parse();
                if (pdu != null && pdu instanceof SendConf) {
                    final SendConf sendConf = (SendConf) pdu;
                    final int responseStatus = sendConf.getResponseStatus();
                    return responseStatus ==
                            PduHeaders.RESPONSE_STATUS_ERROR_PERMANENT_SENDING_ADDRESS_UNRESOLVED ||
                            responseStatus ==
                                    PduHeaders.RESPONSE_STATUS_ERROR_SENDING_ADDRESS_UNRESOLVED;
                }
            } catch (RuntimeException e) {
                Log.w(MmsService.TAG, "Parsing response failed", e);
            }
        }
        return false;
    }

    /**
     * Return the result back via pending intent
     *
     * @param context The context
     * @param result The result code of execution
     * @param response The response body
     * @param httpStatusCode The optional http status code in case of http failure
     */
    void returnResult(final Context context, int result, final byte[] response,
            final int httpStatusCode) {
        if (mPendingIntent == null) {
            // Result not needed
            return;
        }
        // Extra information to send back with the pending intent
        final Intent fillIn = new Intent();
        if (response != null) {
            if (!transferResponse(context, fillIn, response)) {
                // Failed to send PDU data back to caller
                result = SmsManager.MMS_ERROR_IO_ERROR;
            }
        }
        if (result == SmsManager.MMS_ERROR_HTTP_FAILURE && httpStatusCode != 0) {
            // For HTTP failure, fill in the status code for more information
            fillIn.putExtra(SmsManager.EXTRA_MMS_HTTP_STATUS, httpStatusCode);
        }
        try {
            mPendingIntent.send(context, result, fillIn);
        } catch (PendingIntent.CanceledException e) {
            Log.e(MmsService.TAG, "Sending pending intent canceled", e);
        }
    }

    /**
     * Request the route to the APN (either proxy host or the MMSC host)
     *
     * @param connectivityManager the ConnectivityManager to use
     * @param apn the current APN
     * @param url the URL to connect to
     * @throws MmsHttpException for unknown host or route failure
     */
    private static void requestRoute(final ConnectivityManager connectivityManager,
            final ApnSettingsLoader.Apn apn, final String url) throws MmsHttpException {
        String host = apn.getMmsProxy();
        if (TextUtils.isEmpty(host)) {
            final Uri uri = Uri.parse(url);
            host = uri.getHost();
        }
        boolean success = false;
        // Request route to all resolved host addresses
        try {
            for (final InetAddress addr : InetAddress.getAllByName(host)) {
                final boolean requested = requestRouteToHostAddress(connectivityManager, addr);
                if (requested) {
                    success = true;
                    Log.i(MmsService.TAG, "Requested route to " + addr);
                } else {
                    Log.i(MmsService.TAG, "Could not requested route to " + addr);
                }
            }
            if (!success) {
                throw new MmsHttpException(0/*statusCode*/, "No route requested");
            }
        } catch (UnknownHostException e) {
            Log.w(MmsService.TAG, "Unknown host " + host);
            throw new MmsHttpException(0/*statusCode*/, "Unknown host");
        }
    }

    private static final Integer TYPE_MOBILE_MMS =
            Integer.valueOf(ConnectivityManager.TYPE_MOBILE_MMS);
    /**
     * Wrapper for platform API requestRouteToHostAddress
     *
     * We first try the hidden but correct method on ConnectivityManager. If we can't, use
     * the old but buggy one
     *
     * @param connMgr the ConnectivityManager instance
     * @param inetAddr the InetAddress to request
     * @return true if route is successfully setup, false otherwise
     */
    private static boolean requestRouteToHostAddress(final ConnectivityManager connMgr,
            final InetAddress inetAddr) {
        // First try the good method using reflection
        try {
            final Method method = connMgr.getClass().getMethod("requestRouteToHostAddress",
                    Integer.TYPE, InetAddress.class);
            if (method != null) {
                return (Boolean) method.invoke(connMgr, TYPE_MOBILE_MMS, inetAddr);
            }
        } catch (Exception e) {
            Log.w(MmsService.TAG, "ConnectivityManager.requestRouteToHostAddress failed " + e);
        }
        // If we fail, try the old but buggy one
        if (inetAddr instanceof Inet4Address) {
            try {
                final Method method = connMgr.getClass().getMethod("requestRouteToHost",
                        Integer.TYPE, Integer.TYPE);
                if (method != null) {
                    return (Boolean) method.invoke(connMgr, TYPE_MOBILE_MMS,
                        inetAddressToInt(inetAddr));
                }
            } catch (Exception e) {
                Log.w(MmsService.TAG, "ConnectivityManager.requestRouteToHost failed " + e);
            }
        }
        return false;
    }

    /**
     * Convert a IPv4 address from an InetAddress to an integer
     *
     * @param inetAddr is an InetAddress corresponding to the IPv4 address
     * @return the IP address as an integer in network byte order
     */
    private static int inetAddressToInt(final InetAddress inetAddr)
            throws IllegalArgumentException {
        final byte [] addr = inetAddr.getAddress();
        return ((addr[3] & 0xff) << 24) | ((addr[2] & 0xff) << 16) |
                ((addr[1] & 0xff) << 8) | (addr[0] & 0xff);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeByte((byte) (mUseWakeLock ? 1 : 0));
        parcel.writeString(mLocationUrl);
        parcel.writeParcelable(mPduUri, 0);
        parcel.writeParcelable(mPendingIntent, 0);
    }

    protected MmsRequest(final Parcel in) {
        final ClassLoader classLoader = MmsRequest.class.getClassLoader();
        mUseWakeLock = in.readByte() != 0;
        mLocationUrl = in.readString();
        mPduUri = in.readParcelable(classLoader);
        mPendingIntent = in.readParcelable(classLoader);
    }
}
