/*
 * Copyright (C) 2014 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.bluetooth.pan;

import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.net.NetworkAgent;
import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkFactory;
import android.net.ip.IIpClient;
import android.net.ip.IpClientUtil;
import android.net.ip.IpClientUtil.WaitForProvisioningCallbacks;
import android.net.shared.ProvisioningConfiguration;
import android.os.Looper;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;

/**
 * This class tracks the data connection associated with Bluetooth
 * reverse tethering. PanService calls it when a reverse tethered
 * connection needs to be activated or deactivated.
 *
 * @hide
 */
public class BluetoothTetheringNetworkFactory extends NetworkFactory {
    private static final String NETWORK_TYPE = "Bluetooth Tethering";
    private static final String TAG = "BluetoothTetheringNetworkFactory";
    private static final int NETWORK_SCORE = 69;

    private final NetworkCapabilities mNetworkCapabilities;
    private final Context mContext;
    private final PanService mPanService;

    // All accesses to these must be synchronized(this).
    private IIpClient mIpClient;
    @GuardedBy("this")
    private int mIpClientStartIndex = 0;
    private String mInterfaceName;
    private NetworkAgent mNetworkAgent;

    public BluetoothTetheringNetworkFactory(Context context, Looper looper, PanService panService) {
        super(looper, context, NETWORK_TYPE, new NetworkCapabilities());

        mContext = context;
        mPanService = panService;

        mNetworkCapabilities = new NetworkCapabilities();
        initNetworkCapabilities();
        setCapabilityFilter(mNetworkCapabilities);
    }

    private class BtIpClientCallback extends WaitForProvisioningCallbacks {
        private final int mCurrentStartIndex;

        private BtIpClientCallback(int currentStartIndex) {
            mCurrentStartIndex = currentStartIndex;
        }

        @Override
        public void onIpClientCreated(IIpClient ipClient) {
            synchronized (BluetoothTetheringNetworkFactory.this) {
                if (mCurrentStartIndex != mIpClientStartIndex) {
                    // Do not start IpClient: the current request is obsolete.
                    // IpClient will be GCed eventually as the IIpClient Binder token goes out
                    // of scope.
                    return;
                }
                mIpClient = ipClient;
                try {
                    mIpClient.startProvisioning(new ProvisioningConfiguration.Builder()
                            .withoutMultinetworkPolicyTracker()
                            .withoutIpReachabilityMonitor()
                            .build().toStableParcelable());
                } catch (RemoteException e) {
                    Log.e(TAG, "Error starting IpClient provisioning", e);
                }
            }
        }

        @Override
        public void onLinkPropertiesChange(LinkProperties newLp) {
            synchronized (BluetoothTetheringNetworkFactory.this) {
                if (mNetworkAgent != null) {
                    mNetworkAgent.sendLinkProperties(newLp);
                }
            }
        }
    }

    private void stopIpClientLocked() {
        // Mark all previous start requests as obsolete
        mIpClientStartIndex++;
        if (mIpClient != null) {
            try {
                mIpClient.shutdown();
            } catch (RemoteException e) {
                Log.e(TAG, "Error shutting down IpClient", e);
            }
            mIpClient = null;
        }
    }

    private BtIpClientCallback startIpClientLocked() {
        mIpClientStartIndex++;
        final BtIpClientCallback callback = new BtIpClientCallback(mIpClientStartIndex);
        IpClientUtil.makeIpClient(mContext, mInterfaceName, callback);
        return callback;
    }

    // Called by NetworkFactory when PanService and NetworkFactory both desire a Bluetooth
    // reverse-tether connection.  A network interface for Bluetooth reverse-tethering can be
    // assumed to be available because we only register our NetworkFactory when it is so.
    @Override
    protected void startNetwork() {
        // TODO: Figure out how to replace this thread with simple invocations
        // of IpClient. This will likely necessitate a rethink about
        // NetworkAgent and associated instance lifetimes.
        Thread ipProvisioningThread = new Thread(new Runnable() {
            @Override
            public void run() {
                final WaitForProvisioningCallbacks ipcCallback;
                final int ipClientStartIndex;

                synchronized (BluetoothTetheringNetworkFactory.this) {
                    if (TextUtils.isEmpty(mInterfaceName)) {
                        Log.e(TAG, "attempted to reverse tether without interface name");
                        return;
                    }
                    log("ipProvisioningThread(+" + mInterfaceName + ") start IP provisioning");
                    ipcCallback = startIpClientLocked();
                    ipClientStartIndex = mIpClientStartIndex;
                }

                final LinkProperties linkProperties = ipcCallback.waitForProvisioning();
                if (linkProperties == null) {
                    Log.e(TAG, "IP provisioning error.");
                    synchronized (BluetoothTetheringNetworkFactory.this) {
                        stopIpClientLocked();
                        setScoreFilter(-1);
                    }
                    return;
                }
                final NetworkAgentConfig config = new NetworkAgentConfig.Builder()
                        .setLegacyType(ConnectivityManager.TYPE_BLUETOOTH)
                        .setLegacyTypeName(NETWORK_TYPE)
                        .build();

                synchronized (BluetoothTetheringNetworkFactory.this) {
                    // Reverse tethering has been stopped, and stopping won the race : there is
                    // no point in creating the agent (and it would be leaked), so bail.
                    if (ipClientStartIndex != mIpClientStartIndex) return;
                    // Create our NetworkAgent.
                    mNetworkAgent =
                            new NetworkAgent(mContext, getLooper(), NETWORK_TYPE,
                                    mNetworkCapabilities, linkProperties, NETWORK_SCORE,
                                    config, getProvider()) {
                                @Override
                                public void unwanted() {
                                    BluetoothTetheringNetworkFactory.this.onCancelRequest();
                                }
                            };
                    mNetworkAgent.register();
                    mNetworkAgent.markConnected();
                }
            }
        });
        ipProvisioningThread.start();
    }

    // Called from NetworkFactory to indicate ConnectivityService no longer desires a Bluetooth
    // reverse-tether network.
    @Override
    protected void stopNetwork() {
        // Let NetworkAgent disconnect do the teardown.
    }

    // Called by the NetworkFactory, NetworkAgent or PanService to tear down network.
    private synchronized void onCancelRequest() {
        stopIpClientLocked();
        mInterfaceName = "";

        if (mNetworkAgent != null) {
            mNetworkAgent.unregister();
            mNetworkAgent = null;
        }
        for (BluetoothDevice device : mPanService.getConnectedDevices()) {
            mPanService.disconnect(device);
        }
    }

    // Called by PanService when a network interface for Bluetooth reverse-tethering
    // becomes available.  We register our NetworkFactory at this point.
    public void startReverseTether(final String iface) {
        if (iface == null || TextUtils.isEmpty(iface)) {
            Log.e(TAG, "attempted to reverse tether with empty interface");
            return;
        }
        synchronized (this) {
            if (!TextUtils.isEmpty(mInterfaceName)) {
                Log.e(TAG, "attempted to reverse tether while already in process");
                return;
            }
            mInterfaceName = iface;
            // Advertise ourselves to ConnectivityService.
            register();
            setScoreFilter(NETWORK_SCORE);
        }
    }

    // Called by PanService when a network interface for Bluetooth reverse-tethering
    // goes away.  We stop advertising ourselves to ConnectivityService at this point.
    public synchronized void stopReverseTether() {
        if (TextUtils.isEmpty(mInterfaceName)) {
            Log.e(TAG, "attempted to stop reverse tether with nothing tethered");
            return;
        }
        onCancelRequest();
        setScoreFilter(-1);
        terminate();
    }

    private void initNetworkCapabilities() {
        mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_BLUETOOTH);
        mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
        mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
        mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
        mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED);
        // Bluetooth v3 and v4 go up to 24 Mbps.
        // TODO: Adjust this to actual connection bandwidth.
        mNetworkCapabilities.setLinkUpstreamBandwidthKbps(24 * 1000);
        mNetworkCapabilities.setLinkDownstreamBandwidthKbps(24 * 1000);
    }
}
