/*
 * Copyright (C) 2011 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.server;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothTetheringDataTracker;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources.NotFoundException;
import android.net.ConnectivityManager;
import android.net.InterfaceConfiguration;
import android.net.LinkAddress;
import android.net.NetworkUtils;
import android.os.IBinder;
import android.os.INetworkManagementService;
import android.os.ServiceManager;
import android.util.Log;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * This handles the PAN profile. All calls into this are made
 * from Bluetooth Service.
 */
final class BluetoothPanProfileHandler {
    private static final String TAG = "BluetoothPanProfileHandler";
    private static final boolean DBG = true;

    private ArrayList<String> mBluetoothIfaceAddresses;
    private int mMaxPanDevices;

    private static final String BLUETOOTH_IFACE_ADDR_START= "192.168.44.1";
    private static final int BLUETOOTH_MAX_PAN_CONNECTIONS = 5;
    private static final int BLUETOOTH_PREFIX_LENGTH        = 24;
    public static BluetoothPanProfileHandler sInstance;
    private final HashMap<BluetoothDevice, BluetoothPanDevice> mPanDevices;
    private boolean mTetheringOn;
    private Context mContext;
    private BluetoothService mBluetoothService;

    static final String NAP_ROLE = "nap";
    static final String NAP_BRIDGE = "pan1";

    private BluetoothPanProfileHandler(Context context, BluetoothService service) {
        mContext = context;
        mPanDevices = new HashMap<BluetoothDevice, BluetoothPanDevice>();
        mBluetoothService = service;
        mTetheringOn = false;
        mBluetoothIfaceAddresses = new ArrayList<String>();
        try {
            mMaxPanDevices = context.getResources().getInteger(
                            com.android.internal.R.integer.config_max_pan_devices);
        } catch (NotFoundException e) {
            mMaxPanDevices = BLUETOOTH_MAX_PAN_CONNECTIONS;
        }
    }

    static synchronized BluetoothPanProfileHandler getInstance(Context context,
            BluetoothService service) {
        if (sInstance == null) sInstance = new BluetoothPanProfileHandler(context, service);
        return sInstance;
    }

    synchronized boolean isTetheringOn() {
        return mTetheringOn;
    }

    synchronized boolean allowIncomingTethering() {
        if (isTetheringOn() && getConnectedPanDevices().size() < mMaxPanDevices)
            return true;
        return false;
    }

    private BroadcastReceiver mTetheringReceiver = null;

    synchronized void setBluetoothTethering(boolean value) {
        if (!value) {
            disconnectPanServerDevices();
        }

        if (mBluetoothService.getBluetoothState() != BluetoothAdapter.STATE_ON && value) {
            IntentFilter filter = new IntentFilter();
            filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
            mTetheringReceiver = new BroadcastReceiver() {
                @Override
                public synchronized void onReceive(Context context, Intent intent) {
                    if (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF)
                            == BluetoothAdapter.STATE_ON) {
                        mTetheringOn = true;
                        mContext.unregisterReceiver(mTetheringReceiver);
                    }
                }
            };
            mContext.registerReceiver(mTetheringReceiver, filter);
        } else {
            mTetheringOn = value;
        }
    }

    synchronized int getPanDeviceConnectionState(BluetoothDevice device) {
        BluetoothPanDevice panDevice = mPanDevices.get(device);
        if (panDevice == null) {
            return BluetoothPan.STATE_DISCONNECTED;
        }
        return panDevice.mState;
    }

    synchronized boolean connectPanDevice(BluetoothDevice device) {
        String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
        if (DBG) Log.d(TAG, "connect PAN(" + objectPath + ")");
        if (getPanDeviceConnectionState(device) != BluetoothPan.STATE_DISCONNECTED) {
            errorLog(device + " already connected to PAN");
        }

        int connectedCount = 0;
        for (BluetoothDevice panDevice: mPanDevices.keySet()) {
            if (getPanDeviceConnectionState(panDevice) == BluetoothPan.STATE_CONNECTED) {
                connectedCount ++;
            }
        }
        if (connectedCount > 8) {
            debugLog(device + " could not connect to PAN because 8 other devices are"
                    + "already connected");
            return false;
        }

        handlePanDeviceStateChange(device, BluetoothPan.STATE_CONNECTING,
                                           BluetoothPan.LOCAL_PANU_ROLE);
        if (mBluetoothService.connectPanDeviceNative(objectPath, "nap")) {
            debugLog("connecting to PAN");
            return true;
        } else {
            handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTED,
                                                BluetoothPan.LOCAL_PANU_ROLE);
            errorLog("could not connect to PAN");
            return false;
        }
    }

    private synchronized boolean disconnectPanServerDevices() {
        debugLog("disconnect all PAN devices");

        for (BluetoothDevice device: mPanDevices.keySet()) {
            BluetoothPanDevice panDevice = mPanDevices.get(device);
            int state = panDevice.mState;
            if (state == BluetoothPan.STATE_CONNECTED &&
                    panDevice.mLocalRole == BluetoothPan.LOCAL_NAP_ROLE) {
                String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());

                handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTING,
                        panDevice.mLocalRole);

                if (!mBluetoothService.disconnectPanServerDeviceNative(objectPath,
                        device.getAddress(),
                        panDevice.mIfaceAddr)) {
                    errorLog("could not disconnect Pan Server Device "+device.getAddress());

                    // Restore prev state
                    handlePanDeviceStateChange(device, state,
                            panDevice.mLocalRole);

                    return false;
                }
            }
        }
        return true;
    }

    synchronized List<BluetoothDevice> getConnectedPanDevices() {
        List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();

        for (BluetoothDevice device: mPanDevices.keySet()) {
            if (getPanDeviceConnectionState(device) == BluetoothPan.STATE_CONNECTED) {
                devices.add(device);
            }
        }
        return devices;
    }

    synchronized List<BluetoothDevice> getPanDevicesMatchingConnectionStates(int[] states) {
        List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();

        for (BluetoothDevice device: mPanDevices.keySet()) {
            int panDeviceState = getPanDeviceConnectionState(device);
            for (int state : states) {
                if (state == panDeviceState) {
                    devices.add(device);
                    break;
                }
            }
        }
        return devices;
    }

    synchronized boolean disconnectPanDevice(BluetoothDevice device) {
        String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
        debugLog("disconnect PAN(" + objectPath + ")");

        int state = getPanDeviceConnectionState(device);
        if (state != BluetoothPan.STATE_CONNECTED) {
            debugLog(device + " already disconnected from PAN");
            return false;
        }

        BluetoothPanDevice panDevice = mPanDevices.get(device);

        if (panDevice == null) {
            errorLog("No record for this Pan device:" + device);
            return false;
        }

        handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTING,
                                    panDevice.mLocalRole);
        if (panDevice.mLocalRole == BluetoothPan.LOCAL_NAP_ROLE) {
            if (!mBluetoothService.disconnectPanServerDeviceNative(objectPath, device.getAddress(),
                    panDevice.mIface)) {
                // Restore prev state, this shouldn't happen
                handlePanDeviceStateChange(device, state, panDevice.mLocalRole);
                return false;
            }
        } else {
            if (!mBluetoothService.disconnectPanDeviceNative(objectPath)) {
                // Restore prev state, this shouldn't happen
                handlePanDeviceStateChange(device, state, panDevice.mLocalRole);
                return false;
            }
        }
        return true;
    }

    synchronized void handlePanDeviceStateChange(BluetoothDevice device,
                                                 String iface, int state, int role) {
        int prevState;
        String ifaceAddr = null;
        BluetoothPanDevice panDevice = mPanDevices.get(device);

        if (panDevice == null) {
            prevState = BluetoothPan.STATE_DISCONNECTED;
        } else {
            prevState = panDevice.mState;
            ifaceAddr = panDevice.mIfaceAddr;
        }
        if (prevState == state) return;

        if (role == BluetoothPan.LOCAL_NAP_ROLE) {
            if (state == BluetoothPan.STATE_CONNECTED) {
                ifaceAddr = enableTethering(iface);
                if (ifaceAddr == null) Log.e(TAG, "Error seting up tether interface");
            } else if (state == BluetoothPan.STATE_DISCONNECTED) {
                if (ifaceAddr != null) {
                    mBluetoothIfaceAddresses.remove(ifaceAddr);
                    ifaceAddr = null;
                }
            }
        } else {
            // PANU Role = reverse Tether
            if (state == BluetoothPan.STATE_CONNECTED) {
                BluetoothTetheringDataTracker.getInstance().startReverseTether(iface, device);
            } else if (state == BluetoothPan.STATE_DISCONNECTED &&
                  (prevState == BluetoothPan.STATE_CONNECTED ||
                  prevState == BluetoothPan.STATE_DISCONNECTING)) {
                BluetoothTetheringDataTracker.getInstance().stopReverseTether(panDevice.mIface);
            }
        }

        if (panDevice == null) {
            panDevice = new BluetoothPanDevice(state, ifaceAddr, iface, role);
            mPanDevices.put(device, panDevice);
        } else {
            panDevice.mState = state;
            panDevice.mIfaceAddr = ifaceAddr;
            panDevice.mLocalRole = role;
        }

        Intent intent = new Intent(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        intent.putExtra(BluetoothPan.EXTRA_PREVIOUS_STATE, prevState);
        intent.putExtra(BluetoothPan.EXTRA_STATE, state);
        intent.putExtra(BluetoothPan.EXTRA_LOCAL_ROLE, role);
        mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM);

        debugLog("Pan Device state : device: " + device + " State:" + prevState + "->" + state);
        mBluetoothService.sendConnectionStateChange(device, state, prevState);
    }

    synchronized void handlePanDeviceStateChange(BluetoothDevice device,
                                                 int state, int role) {
        handlePanDeviceStateChange(device, null, state, role);
    }

    private class BluetoothPanDevice {
        private int mState;
        private String mIfaceAddr;
        private String mIface;
        private int mLocalRole; // Which local role is this PAN device bound to

        BluetoothPanDevice(int state, String ifaceAddr, String iface, int localRole) {
            mState = state;
            mIfaceAddr = ifaceAddr;
            mIface = iface;
            mLocalRole = localRole;
        }
    }

    private String createNewTetheringAddressLocked() {
        if (getConnectedPanDevices().size() == mMaxPanDevices) {
            debugLog ("Max PAN device connections reached");
            return null;
        }
        String address = BLUETOOTH_IFACE_ADDR_START;
        while (true) {
            if (mBluetoothIfaceAddresses.contains(address)) {
                String[] addr = address.split("\\.");
                Integer newIp = Integer.parseInt(addr[2]) + 1;
                address = address.replace(addr[2], newIp.toString());
            } else {
                break;
            }
        }
        mBluetoothIfaceAddresses.add(address);
        return address;
    }

    // configured when we start tethering
    private synchronized String enableTethering(String iface) {
        debugLog("updateTetherState:" + iface);

        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
        INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
        ConnectivityManager cm =
            (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        String[] bluetoothRegexs = cm.getTetherableBluetoothRegexs();

        // bring toggle the interfaces
        String[] currentIfaces = new String[0];
        try {
            currentIfaces = service.listInterfaces();
        } catch (Exception e) {
            Log.e(TAG, "Error listing Interfaces :" + e);
            return null;
        }

        boolean found = false;
        for (String currIface: currentIfaces) {
            if (currIface.equals(iface)) {
                found = true;
                break;
            }
        }

        if (!found) return null;

        String address = createNewTetheringAddressLocked();
        if (address == null) return null;

        InterfaceConfiguration ifcg = null;
        try {
            ifcg = service.getInterfaceConfig(iface);
            if (ifcg != null) {
                InetAddress addr = null;
                if (ifcg.addr == null || (addr = ifcg.addr.getAddress()) == null ||
                        addr.equals(NetworkUtils.numericToInetAddress("0.0.0.0")) ||
                        addr.equals(NetworkUtils.numericToInetAddress("::0"))) {
                    addr = NetworkUtils.numericToInetAddress(address);
                }
                ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
                ifcg.addr = new LinkAddress(addr, BLUETOOTH_PREFIX_LENGTH);
                ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", "");
                ifcg.interfaceFlags = ifcg.interfaceFlags.replace("  "," ");
                service.setInterfaceConfig(iface, ifcg);
                if (cm.tether(iface) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
                    Log.e(TAG, "Error tethering "+iface);
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "Error configuring interface " + iface + ", :" + e);
            return null;
        }
        return address;
    }

    private static void debugLog(String msg) {
        if (DBG) Log.d(TAG, msg);
    }

    private static void errorLog(String msg) {
        Log.e(TAG, msg);
    }
}
