/*
 * Copyright (C) 2019 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.settings.network;

import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
import static android.net.ConnectivityManager.TETHERING_USB;
import static android.net.ConnectivityManager.TETHERING_WIFI;
import static android.net.TetheringManager.TETHERING_ETHERNET;

import static java.lang.annotation.RetentionPolicy.SOURCE;

import android.annotation.IntDef;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothPan;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.EthernetManager;
import android.net.IpConfiguration;
import android.net.TetheringManager;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
import android.os.UserManager;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;

import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.datausage.DataSaverBackend;
import com.android.settings.widget.SwitchWidgetController;

import java.lang.annotation.Retention;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;

/**
 * TetherEnabler is a helper to manage Tethering switch on/off state. It offers helper functions to
 * turn on/off different types of tethering interfaces and ensures tethering state updated by data
 * saver state.
 *
 * This class is not designed for extending. It's extendable solely for the test purpose.
 */

public class TetherEnabler implements SwitchWidgetController.OnSwitchChangeListener,
        DataSaverBackend.Listener, LifecycleObserver {

    /**
     * Interface definition for a callback to be invoked when the tethering has been updated.
     */
    public interface OnTetherStateUpdateListener {
        /**
         * Called when the tethering state has changed.
         *
         * @param state The new tethering state.
         */
        void onTetherStateUpdated(@TetheringState int state);
    }

    private static final String TAG = "TetherEnabler";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);

    private final class EthernetListener implements EthernetManager.InterfaceStateListener {
        public void onInterfaceStateChanged(@NonNull String iface, int state, int role,
                @NonNull IpConfiguration configuration) {
            if (state == EthernetManager.STATE_LINK_UP) {
                mAvailableInterfaces.put(iface, configuration);
            } else {
                mAvailableInterfaces.remove(iface, configuration);
            }
        }
    }

    @Retention(SOURCE)
    @IntDef(
            flag = true,
            value = {
                    TETHERING_OFF,
                    TETHERING_WIFI_ON,
                    TETHERING_USB_ON,
                    TETHERING_BLUETOOTH_ON,
                    TETHERING_ETHERNET_ON
            }
    )
    @interface TetheringState {}
    public static final int TETHERING_OFF = 0;
    public static final int TETHERING_WIFI_ON = 1 << TETHERING_WIFI;
    public static final int TETHERING_USB_ON = 1 << TETHERING_USB;
    public static final int TETHERING_BLUETOOTH_ON = 1 << TETHERING_BLUETOOTH;
    public static final int TETHERING_ETHERNET_ON = 1 << TETHERING_ETHERNET;

    @VisibleForTesting
    final List<OnTetherStateUpdateListener> mListeners;
    private final Handler mMainThreadHandler;
    private final SwitchWidgetController mSwitchWidgetController;
    private final WifiManager mWifiManager;
    private final ConnectivityManager mConnectivityManager;
    private final TetheringManager mTetheringManager;
    private final UserManager mUserManager;
    private final DataSaverBackend mDataSaverBackend;
    private boolean mDataSaverEnabled;
    @VisibleForTesting
    boolean mBluetoothTetheringStoppedByUser;
    private final Context mContext;
    @VisibleForTesting
    TetheringManager.TetheringEventCallback mTetheringEventCallback;
    @VisibleForTesting
    ConnectivityManager.OnStartTetheringCallback mOnStartTetheringCallback;
    private final AtomicReference<BluetoothPan> mBluetoothPan;
    private boolean mBluetoothEnableForTether;
    private final BluetoothAdapter mBluetoothAdapter;
    private final EthernetManager mEthernetManager;
    private final EthernetManager.InterfaceStateListener mEthernetListener = new EthernetListener();
    private final ConcurrentHashMap<String, IpConfiguration> mAvailableInterfaces =
            new ConcurrentHashMap<>();

    public TetherEnabler(Context context, SwitchWidgetController switchWidgetController,
            AtomicReference<BluetoothPan> bluetoothPan) {
        mContext = context;
        mSwitchWidgetController = switchWidgetController;
        mDataSaverBackend = new DataSaverBackend(context);
        mConnectivityManager =
                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        mTetheringManager = (TetheringManager) context.getSystemService(Context.TETHERING_SERVICE);
        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        mBluetoothPan = bluetoothPan;
        mDataSaverEnabled = mDataSaverBackend.isDataSaverEnabled();
        mListeners = new ArrayList<>();
        mMainThreadHandler = new Handler(Looper.getMainLooper());
        mEthernetManager = context.getSystemService(EthernetManager.class);
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    public void onStart() {
        mDataSaverBackend.addListener(this);
        mSwitchWidgetController.setListener(this);
        mSwitchWidgetController.startListening();
        final IntentFilter filter = new IntentFilter(
                TetheringManager.ACTION_TETHER_STATE_CHANGED);
        filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        mContext.registerReceiver(mTetherChangeReceiver, filter);
        mTetheringEventCallback  =
                new TetheringManager.TetheringEventCallback() {
                    @Override
                    public void onTetheredInterfacesChanged(List<String> interfaces) {
                        updateState(interfaces.toArray(new String[interfaces.size()]));
                    }
                };
        mTetheringManager.registerTetheringEventCallback(new HandlerExecutor(mMainThreadHandler),
                mTetheringEventCallback);

        mOnStartTetheringCallback = new OnStartTetheringCallback(this);
        updateState(null/*tethered*/);
        if (mEthernetManager != null) {
            mEthernetManager.addInterfaceStateListener(r -> mMainThreadHandler.post(r),
                    mEthernetListener);
        }
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    public void onStop() {
        mBluetoothTetheringStoppedByUser = false;
        mDataSaverBackend.remListener(this);
        mSwitchWidgetController.stopListening();
        mContext.unregisterReceiver(mTetherChangeReceiver);
        mTetheringManager.unregisterTetheringEventCallback(mTetheringEventCallback);
        mTetheringEventCallback = null;
        if (mEthernetManager != null) {
            mEthernetManager.removeInterfaceStateListener(mEthernetListener);
        }
    }

    public void addListener(OnTetherStateUpdateListener listener) {
        if (listener != null && !mListeners.contains(listener)) {
            listener.onTetherStateUpdated(getTetheringState(null /* tethered */));
            mListeners.add(listener);
        }
    }

    public void removeListener(OnTetherStateUpdateListener listener) {
        if (listener != null) {
            mListeners.remove(listener);
        }
    }

    private void setSwitchEnabled(boolean enabled) {
        mSwitchWidgetController.setEnabled(
                enabled && !mDataSaverEnabled && mUserManager.isAdminUser());
    }

    @VisibleForTesting
    void updateState(@Nullable String[] tethered) {
        int state = getTetheringState(tethered);
        if (DEBUG) {
            Log.d(TAG, "updateState: " + state);
        }
        setSwitchCheckedInternal(state != TETHERING_OFF);
        setSwitchEnabled(true);
        for (int i = 0, size = mListeners.size(); i < size; ++i) {
            mListeners.get(i).onTetherStateUpdated(state);
        }
    }

    private void setSwitchCheckedInternal(boolean checked) {
        try {
            mSwitchWidgetController.stopListening();
        } catch (IllegalStateException e) {
            Log.e(TAG, "failed to stop switch widget listener when set check internally");
            return;
        }
        mSwitchWidgetController.setChecked(checked);
        mSwitchWidgetController.startListening();
    }

    @VisibleForTesting
    @TetheringState
    int getTetheringState(@Nullable String[] tethered) {
        int tetherState = TETHERING_OFF;
        if (tethered == null) {
            tethered = mTetheringManager.getTetheredIfaces();
        }

        if (mWifiManager.isWifiApEnabled()) {
            tetherState |= TETHERING_WIFI_ON;
        }

        // Only check bluetooth tethering state if not stopped by user already.
        if (!mBluetoothTetheringStoppedByUser) {
            final BluetoothPan pan = mBluetoothPan.get();
            if (mBluetoothAdapter != null &&
                mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON
                    && pan != null && pan.isTetheringOn()) {
                tetherState |= TETHERING_BLUETOOTH_ON;
            }
        }

        String[] usbRegexs = mTetheringManager.getTetherableUsbRegexs();
        for (String s : tethered) {
            for (String regex : usbRegexs) {
                if (s.matches(regex)) {
                    tetherState |= TETHERING_USB_ON;
                }
            }
            if (mAvailableInterfaces.containsKey(s)) {
                tetherState |= TETHERING_ETHERNET_ON;
            }
        }

        return tetherState;
    }

    public static boolean isTethering(@TetheringState int state, int choice) {
        return (state & (1 << choice)) != TETHERING_OFF;
    }

    @Override
    public boolean onSwitchToggled(boolean isChecked) {
        if (isChecked) {
            startTethering(TETHERING_WIFI);
        } else {
            stopTethering(TETHERING_USB);
            stopTethering(TETHERING_WIFI);
            stopTethering(TETHERING_BLUETOOTH);
            stopTethering(TETHERING_ETHERNET);
        }
        return true;
    }

    public void stopTethering(int choice) {
        int state = getTetheringState(null /* tethered */);
        if (isTethering(state, choice)) {
            setSwitchEnabled(false);
            mConnectivityManager.stopTethering(choice);
            if (choice == TETHERING_BLUETOOTH) {
                // Stop bluetooth tether won't invoke tether state changed callback, so we need this
                // boolean to remember the user action and update UI state immediately.
                mBluetoothTetheringStoppedByUser = true;
                updateState(null /* tethered */);
            }
        }
    }

    public void startTethering(int choice) {
        if (choice == TETHERING_BLUETOOTH) {
            mBluetoothTetheringStoppedByUser = false;
        }
        int state = getTetheringState(null /* tethered */);
        if (isTethering(state, choice)) {
            return;
        }

        if (choice == TETHERING_BLUETOOTH && mBluetoothAdapter != null
                && mBluetoothAdapter.getState() == BluetoothAdapter.STATE_OFF) {
            if (DEBUG) {
                Log.d(TAG, "Turn on bluetooth first.");
            }
            mBluetoothEnableForTether = true;
            mBluetoothAdapter.enable();
            return;
        }

        setSwitchEnabled(false);
        mConnectivityManager.startTethering(choice, true /* showProvisioningUi */,
                mOnStartTetheringCallback, mMainThreadHandler);
    }

    private final BroadcastReceiver mTetherChangeReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            boolean shouldUpdateState = false;
            if (TextUtils.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION, action)) {
                shouldUpdateState = handleWifiApStateChanged(intent.getIntExtra(
                        WifiManager.EXTRA_WIFI_AP_STATE, WifiManager.WIFI_AP_STATE_FAILED));
            } else if (TextUtils.equals(BluetoothAdapter.ACTION_STATE_CHANGED, action)) {
                shouldUpdateState = handleBluetoothStateChanged(intent
                        .getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR));
            }

            if (shouldUpdateState) {
                updateState(null /* tethered */);
            }
        }
    };

    private boolean handleBluetoothStateChanged(int state) {
        switch (state) {
            case BluetoothAdapter.STATE_ON:
                if (mBluetoothEnableForTether) {
                    startTethering(TETHERING_BLUETOOTH);
                }
                // Fall through.
            case BluetoothAdapter.STATE_OFF:
                // Fall through.
            case BluetoothAdapter.ERROR:
                mBluetoothEnableForTether = false;
                return true;
            default:
                // Return false for transition states.
                return false;
        }
    }

    private boolean handleWifiApStateChanged(int state) {
        switch (state) {
            case WifiManager.WIFI_AP_STATE_FAILED:
                Log.e(TAG, "Wifi AP is failed!");
                // fall through
            case WifiManager.WIFI_AP_STATE_ENABLED:
                // fall through
            case WifiManager.WIFI_AP_STATE_DISABLED:
                return true;
            default:
                // return false for transition state
                return false;
        }
    }

    @Override
    public void onDataSaverChanged(boolean isDataSaving) {
        mDataSaverEnabled = isDataSaving;
        setSwitchEnabled(true);
    }

    @Override
    public void onAllowlistStatusChanged(int uid, boolean isAllowlisted) {
        // we don't care, since we just want to read the value
    }

    @Override
    public void onDenylistStatusChanged(int uid, boolean isDenylisted) {
        // we don't care, since we just want to read the value
    }

    private static final class OnStartTetheringCallback extends
            ConnectivityManager.OnStartTetheringCallback {
        final WeakReference<TetherEnabler> mTetherEnabler;

        OnStartTetheringCallback(TetherEnabler enabler) {
            mTetherEnabler = new WeakReference<>(enabler);
        }

        @Override
        public void onTetheringStarted() {
            update();
        }

        @Override
        public void onTetheringFailed() {
            update();
        }

        private void update() {
            TetherEnabler enabler = mTetherEnabler.get();
            if (enabler != null) {
                enabler.updateState(null/*tethered*/);
            }
        }
    }
}
