/*
 * 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.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.SystemClock;
import android.util.Log;

import java.lang.reflect.Method;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Class manages MMS network connectivity using legacy platform APIs
 * (deprecated since Android L) on pre-L devices (or when forced to
 * be used on L and later)
 */
class MmsNetworkManager {
    // Hidden platform constants
    private static final String FEATURE_ENABLE_MMS = "enableMMS";
    private static final String REASON_VOICE_CALL_ENDED = "2GVoiceCallEnded";
    private static final int APN_ALREADY_ACTIVE     = 0;
    private static final int APN_REQUEST_STARTED    = 1;
    private static final int APN_TYPE_NOT_AVAILABLE = 2;
    private static final int APN_REQUEST_FAILED     = 3;
    private static final int APN_ALREADY_INACTIVE   = 4;
    // A map from platform APN constant to text string
    private static final String[] APN_RESULT_STRING = new String[]{
            "already active",
            "request started",
            "type not available",
            "request failed",
            "already inactive",
            "unknown",
    };

    private static final long NETWORK_ACQUIRE_WAIT_INTERVAL_MS = 15000;
    private static final long DEFAULT_NETWORK_ACQUIRE_TIMEOUT_MS = 180000;
    private static final String MMS_NETWORK_EXTENSION_TIMER = "mms_network_extension_timer";
    private static final long MMS_NETWORK_EXTENSION_TIMER_WAIT_MS = 30000;

    private static volatile long sNetworkAcquireTimeoutMs = DEFAULT_NETWORK_ACQUIRE_TIMEOUT_MS;

    /**
     * Set the network acquire timeout
     *
     * @param timeoutMs timeout in millisecond
     */
    static void setNetworkAcquireTimeout(final long timeoutMs) {
        sNetworkAcquireTimeoutMs = timeoutMs;
    }

    private final Context mContext;
    private final ConnectivityManager mConnectivityManager;

    // If the connectivity intent receiver is registered
    private boolean mReceiverRegistered;
    // Count of requests that are using the MMS network
    private int mUseCount;
    // Count of requests that are waiting for connectivity (i.e. in acquireNetwork wait loop)
    private int mWaitCount;
    // Timer to extend the network connectivity
    private Timer mExtensionTimer;

    private final MmsHttpClient mHttpClient;

    private final IntentFilter mConnectivityIntentFilter;
    private final BroadcastReceiver mConnectivityChangeReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(final Context context, final Intent intent) {
            if (!ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
                return;
            }
            final int networkType = getConnectivityChangeNetworkType(intent);
            if (networkType != ConnectivityManager.TYPE_MOBILE_MMS) {
                return;
            }
            onMmsConnectivityChange(context, intent);
        }
    };

    MmsNetworkManager(final Context context) {
        mContext = context;
        mConnectivityManager = (ConnectivityManager) mContext.getSystemService(
                Context.CONNECTIVITY_SERVICE);
        mHttpClient = new MmsHttpClient(mContext);
        mConnectivityIntentFilter = new IntentFilter();
        mConnectivityIntentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        mUseCount = 0;
        mWaitCount = 0;
    }

    ConnectivityManager getConnectivityManager() {
        return mConnectivityManager;
    }

    MmsHttpClient getHttpClient() {
        return mHttpClient;
    }

    /**
     * Synchronously acquire MMS network connectivity
     *
     * @throws MmsNetworkException If failed permanently or timed out
     */
    void acquireNetwork() throws MmsNetworkException {
        Log.i(MmsService.TAG, "Acquire MMS network");
        synchronized (this) {
            try {
                mUseCount++;
                mWaitCount++;
                if (mWaitCount == 1) {
                    // Register the receiver for the first waiting request
                    registerConnectivityChangeReceiverLocked();
                }
                long waitMs = sNetworkAcquireTimeoutMs;
                final long beginMs = SystemClock.elapsedRealtime();
                do {
                    if (!isMobileDataEnabled()) {
                        // Fast fail if mobile data is not enabled
                        throw new MmsNetworkException("Mobile data is disabled");
                    }
                    // Always try to extend and check the MMS network connectivity
                    // before we start waiting to make sure we don't miss the change
                    // of MMS connectivity. As one example, some devices fail to send
                    // connectivity change intent. So this would make sure we catch
                    // the state change.
                    if (extendMmsConnectivityLocked()) {
                        // Connected
                        return;
                    }
                    try {
                        wait(Math.min(waitMs, NETWORK_ACQUIRE_WAIT_INTERVAL_MS));
                    } catch (final InterruptedException e) {
                        Log.w(MmsService.TAG, "Unexpected exception", e);
                    }
                    // Calculate the remaining time to wait
                    waitMs = sNetworkAcquireTimeoutMs - (SystemClock.elapsedRealtime() - beginMs);
                } while (waitMs > 0);
                // Last check
                if (extendMmsConnectivityLocked()) {
                    return;
                } else {
                    // Reaching here means timed out.
                    throw new MmsNetworkException("Acquiring MMS network timed out");
                }
            } finally {
                mWaitCount--;
                if (mWaitCount == 0) {
                    // Receiver is used to listen to connectivity change and unblock
                    // the waiting requests. If nobody's waiting on change, there is
                    // no need for the receiver. The auto extension timer will try
                    // to maintain the connectivity periodically.
                    unregisterConnectivityChangeReceiverLocked();
                }
            }
        }
    }

    /**
     * Release MMS network connectivity. This is ref counted. So it only disconnect
     * when the ref count is 0.
     */
    void releaseNetwork() {
        Log.i(MmsService.TAG, "release MMS network");
        synchronized (this) {
            mUseCount--;
            if (mUseCount == 0) {
                stopNetworkExtensionTimerLocked();
                endMmsConnectivity();
            }
        }
    }

    String getApnName() {
        String apnName = null;
        final NetworkInfo mmsNetworkInfo = mConnectivityManager.getNetworkInfo(
                ConnectivityManager.TYPE_MOBILE_MMS);
        if (mmsNetworkInfo != null) {
            apnName = mmsNetworkInfo.getExtraInfo();
        }
        return apnName;
    }

    // Process mobile MMS connectivity change, waking up the waiting request thread
    // in certain conditions:
    // - Successfully connected
    // - Failed permanently
    // - Required another kickoff
    // We don't initiate connection here but just notifyAll so the waiting request
    // would wake up and retry connection before next wait.
    private void onMmsConnectivityChange(final Context context, final Intent intent) {
        if (mUseCount < 1) {
            return;
        }
        final NetworkInfo mmsNetworkInfo =
                mConnectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_MMS);
        // Check availability of the mobile network.
        if (mmsNetworkInfo != null) {
            if (REASON_VOICE_CALL_ENDED.equals(mmsNetworkInfo.getReason())) {
                // This is a very specific fix to handle the case where the phone receives an
                // incoming call during the time we're trying to setup the mms connection.
                // When the call ends, restart the process of mms connectivity.
                // Once the waiting request is unblocked, before the next wait, we would start
                // MMS network again.
                unblockWait();
            } else {
                final NetworkInfo.State state = mmsNetworkInfo.getState();
                if (state == NetworkInfo.State.CONNECTED ||
                        (state == NetworkInfo.State.DISCONNECTED && !isMobileDataEnabled())) {
                    // Unblock the waiting request when we either connected
                    // OR
                    // disconnected due to mobile data disabled therefore needs to fast fail
                    // (on some devices if mobile data disabled and starting MMS would cause
                    // an immediate state change to disconnected, so causing a tight loop of
                    // trying and failing)
                    // Once the waiting request is unblocked, before the next wait, we would
                    // check mobile data and start MMS network again. So we should catch
                    // both the success and the fast failure.
                    unblockWait();
                }
            }
        }
    }

    private void unblockWait() {
        synchronized (this) {
            notifyAll();
        }
    }

    private void startNetworkExtensionTimerLocked() {
        if (mExtensionTimer == null) {
            mExtensionTimer = new Timer(MMS_NETWORK_EXTENSION_TIMER, true/*daemon*/);
            mExtensionTimer.schedule(
                    new TimerTask() {
                        @Override
                        public void run() {
                            synchronized (this) {
                                if (mUseCount > 0) {
                                    try {
                                        // Try extending the connectivity
                                        extendMmsConnectivityLocked();
                                    } catch (final MmsNetworkException e) {
                                        // Ignore the exception
                                    }
                                }
                            }
                        }
                    },
                    MMS_NETWORK_EXTENSION_TIMER_WAIT_MS);
        }
    }

    private void stopNetworkExtensionTimerLocked() {
        if (mExtensionTimer != null) {
            mExtensionTimer.cancel();
            mExtensionTimer = null;
        }
    }

    private boolean extendMmsConnectivityLocked() throws MmsNetworkException {
        final int result = startMmsConnectivity();
        if (result == APN_ALREADY_ACTIVE) {
            // Already active
            startNetworkExtensionTimerLocked();
            return true;
        } else if (result != APN_REQUEST_STARTED) {
            stopNetworkExtensionTimerLocked();
            throw new MmsNetworkException("Cannot acquire MMS network: " +
                    result + " - " + getMmsConnectivityResultString(result));
        }
        return false;
    }

    private int startMmsConnectivity() {
        Log.i(MmsService.TAG, "Start MMS connectivity");
        try {
            final Method method = mConnectivityManager.getClass().getMethod(
                "startUsingNetworkFeature", Integer.TYPE, String.class);
            if (method != null) {
                return (Integer) method.invoke(
                    mConnectivityManager, ConnectivityManager.TYPE_MOBILE, FEATURE_ENABLE_MMS);
            }
        } catch (final Exception e) {
            Log.w(MmsService.TAG, "ConnectivityManager.startUsingNetworkFeature failed " + e);
        }
        return APN_REQUEST_FAILED;
    }

    private void endMmsConnectivity() {
        Log.i(MmsService.TAG, "End MMS connectivity");
        try {
            final Method method = mConnectivityManager.getClass().getMethod(
                "stopUsingNetworkFeature", Integer.TYPE, String.class);
            if (method != null) {
                method.invoke(
                        mConnectivityManager, ConnectivityManager.TYPE_MOBILE, FEATURE_ENABLE_MMS);
            }
        } catch (final Exception e) {
            Log.w(MmsService.TAG, "ConnectivityManager.stopUsingNetworkFeature failed " + e);
        }
    }

    private void registerConnectivityChangeReceiverLocked() {
        if (!mReceiverRegistered) {
            mContext.registerReceiver(mConnectivityChangeReceiver, mConnectivityIntentFilter);
            mReceiverRegistered = true;
        }
    }

    private void unregisterConnectivityChangeReceiverLocked() {
        if (mReceiverRegistered) {
            mContext.unregisterReceiver(mConnectivityChangeReceiver);
            mReceiverRegistered = false;
        }
    }

    /**
     * The absence of a connection type.
     */
    private static final int TYPE_NONE = -1;

    /**
     * Get the network type of the connectivity change
     *
     * @param intent the broadcast intent of connectivity change
     * @return The change's network type
     */
    private static int getConnectivityChangeNetworkType(final Intent intent) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            return intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, TYPE_NONE);
        } else {
            final NetworkInfo info = intent.getParcelableExtra(
                    ConnectivityManager.EXTRA_NETWORK_INFO);
            if (info != null) {
                return info.getType();
            }
        }
        return TYPE_NONE;
    }

    private static String getMmsConnectivityResultString(int result) {
        if (result < 0 || result >= APN_RESULT_STRING.length) {
            result = APN_RESULT_STRING.length - 1;
        }
        return APN_RESULT_STRING[result];
    }

    private boolean isMobileDataEnabled() {
        try {
            final Class cmClass = mConnectivityManager.getClass();
            final Method method = cmClass.getDeclaredMethod("getMobileDataEnabled");
            method.setAccessible(true); // Make the method callable
            // get the setting for "mobile data"
            return (Boolean) method.invoke(mConnectivityManager);
        } catch (final Exception e) {
            Log.w(MmsService.TAG, "TelephonyManager.getMobileDataEnabled failed", e);
        }
        return false;
    }
}
