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

import android.app.ProgressDialog;
import android.content.Intent;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.NetworkRequestMatchCallback;
import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Message;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.FragmentActivity;

import com.android.settings.R;
import com.android.settings.wifi.NetworkRequestErrorDialogFragment.ERROR_DIALOG_TYPE;

import java.util.List;

/**
 * When other applications request to have a wifi connection, framework will bring up this activity
 * to let user select which wifi ap wanna to connect. This activity contains
 * {@code NetworkRequestDialogFragment}, {@code NetworkRequestSingleSsidDialogFragment} to show UI
 * and handles framework callback.
 */
public class NetworkRequestDialogActivity extends FragmentActivity implements
        NetworkRequestMatchCallback {
    private static String TAG = "NetworkRequestDialogActivity";

    /** Message sent to stop scanning wifi and pop up timeout dialog. */
    private static final int MESSAGE_STOP_SCAN_WIFI_LIST = 0;

    /** Delayed time to stop scanning wifi. */
    private static final int DELAY_TIME_STOP_SCAN_MS = 30 * 1000;

    final static String EXTRA_IS_SPECIFIED_SSID =
        "com.android.settings.wifi.extra.REQUEST_IS_FOR_SINGLE_NETWORK";

    @VisibleForTesting NetworkRequestDialogBaseFragment mDialogFragment;
    private NetworkRequestUserSelectionCallback mUserSelectionCallback;
    private boolean mIsSpecifiedSsid;
    private boolean mShowingErrorDialog;
    private WifiConfiguration mMatchedConfig;
    @VisibleForTesting ProgressDialog mProgressDialog;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        final Intent intent = getIntent();
        if (intent != null) {
            mIsSpecifiedSsid = intent.getBooleanExtra(EXTRA_IS_SPECIFIED_SSID, false);
        }

        if (mIsSpecifiedSsid) {
            showProgressDialog(getString(R.string.network_connection_searching_message));
        } else {
            mDialogFragment = NetworkRequestDialogFragment.newInstance();
            mDialogFragment.show(getSupportFragmentManager(), TAG);
        }
    }

    private void showProgressDialog(String message) {
        dismissDialogs();

        mProgressDialog = new ProgressDialog(this);
        mProgressDialog.setIndeterminate(true);
        mProgressDialog.setCancelable(false);
        mProgressDialog.setMessage(message);
        mProgressDialog.show();
    }

    private void showSingleSsidRequestDialog(String ssid, boolean isTryAgain) {
        dismissDialogs();

        mDialogFragment = new NetworkRequestSingleSsidDialogFragment();
        final Bundle bundle = new Bundle();
        bundle.putString(NetworkRequestSingleSsidDialogFragment.EXTRA_SSID, ssid);
        bundle.putBoolean(NetworkRequestSingleSsidDialogFragment.EXTRA_TRYAGAIN, isTryAgain);
        mDialogFragment.setArguments(bundle);
        mDialogFragment.show(getSupportFragmentManager(), TAG);
    }

    private void dismissDialogs() {
        if (mDialogFragment != null) {
            mDialogFragment.dismiss();
            mDialogFragment = null;
        }
        if (mProgressDialog != null) {
            mProgressDialog.dismiss();
            mProgressDialog = null;
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        final WifiManager wifiManager = getSystemService(WifiManager.class);
        if (wifiManager != null) {
            wifiManager.registerNetworkRequestMatchCallback(new HandlerExecutor(mHandler), this);
        }
        // Sets time-out to stop scanning.
        mHandler.sendEmptyMessageDelayed(MESSAGE_STOP_SCAN_WIFI_LIST, DELAY_TIME_STOP_SCAN_MS);
    }

    @Override
    protected void onPause() {
        mHandler.removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST);
        final WifiManager wifiManager = getSystemService(WifiManager.class);
        if (wifiManager != null) {
            wifiManager.unregisterNetworkRequestMatchCallback(this);
        }

        super.onPause();
    }

    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MESSAGE_STOP_SCAN_WIFI_LIST:
                    removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST);
                    stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE.TIME_OUT);
                    break;
                default:
                    // Do nothing.
                    break;
            }
        }
    };

    protected void stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE type) {
        dismissDialogs();

        // Throws error dialog.
        final NetworkRequestErrorDialogFragment dialogFragment =
                NetworkRequestErrorDialogFragment.newInstance();
        dialogFragment.setRejectCallback(mUserSelectionCallback);
        final Bundle bundle = new Bundle();
        bundle.putSerializable(NetworkRequestErrorDialogFragment.DIALOG_TYPE, type);
        dialogFragment.setArguments(bundle);
        dialogFragment.show(getSupportFragmentManager(), TAG);
        mShowingErrorDialog = true;
    }

    @Override
    public void onUserSelectionCallbackRegistration(
        NetworkRequestUserSelectionCallback userSelectionCallback) {
        if (mIsSpecifiedSsid) {
            mUserSelectionCallback = userSelectionCallback;
            return;
        }

        mDialogFragment.onUserSelectionCallbackRegistration(userSelectionCallback);
    }

    @Override
    public void onAbort() {
        stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE.ABORT);
    }

    @Override
    public void onMatch(List<ScanResult> scanResults) {
        if (mShowingErrorDialog) {
            // Don't do anything since error dialog shows.
            return;
        }

        mHandler.removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST);

        if (mIsSpecifiedSsid) {
            // Prevent from throwing same dialog, because onMatch() will be called many times.
            if (mMatchedConfig == null) {
                mMatchedConfig = WifiUtils.getWifiConfig(null /* wifiEntry */, scanResults.get(0));
                showSingleSsidRequestDialog(
                        WifiInfo.sanitizeSsid(mMatchedConfig.SSID), false /* isTryAgain */);
            }
            return;
        }

        mDialogFragment.onMatch(scanResults);
    }

    @Override
    public void onUserSelectionConnectSuccess(WifiConfiguration wificonfiguration) {
        if (!isFinishing()) {
            Toast.makeText(this, R.string.network_connection_connect_successful, Toast.LENGTH_SHORT)
                    .show();
            setResult(RESULT_OK);
            finish();
        }
    }

    @Override
    public void onUserSelectionConnectFailure(WifiConfiguration wificonfiguration) {
        if (!isFinishing()) {
            Toast.makeText(this, R.string.network_connection_connect_failure, Toast.LENGTH_SHORT)
                    .show();
            setResult(RESULT_OK);
            finish();
        }
    }

    // Called when user click "Connect" button. Called by
    // {@code NetworkRequestSingleSsidDialogFragment}.
    public void onClickConnectButton() {
        if (mUserSelectionCallback != null) {
            mUserSelectionCallback.select(mMatchedConfig);
            showProgressDialog(getString(R.string.network_connection_connecting_message));
        }
    }

    // Called when user click retry button. Called by {@link NetworkRequestErrorDialogFragment}.
    public void onClickRescanButton() {
        // Sets time-out to stop scanning.
        mHandler.sendEmptyMessageDelayed(MESSAGE_STOP_SCAN_WIFI_LIST, DELAY_TIME_STOP_SCAN_MS);

        mShowingErrorDialog = false;

        if (mIsSpecifiedSsid) {
            mMatchedConfig = null;
            showProgressDialog(getString(R.string.network_connection_searching_message));
        } else {
            mDialogFragment = NetworkRequestDialogFragment.newInstance();
            mDialogFragment.show(getSupportFragmentManager(), TAG);
        }
    }

    // Called when user click cancel button.
    public void onCancel() {
        dismissDialogs();

        if (mUserSelectionCallback != null) {
            mUserSelectionCallback.reject();
        }
        finish();
    }
}
