/*
 * 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 static com.android.settings.wifi.WifiUtils.getWifiEntrySecurity;

import static java.util.stream.Collectors.toList;

import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.drawable.Drawable;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Process;
import android.os.SimpleClock;
import android.os.SystemClock;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.internal.PreferenceImageView;

import com.android.settings.R;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.Utils;
import com.android.wifitrackerlib.WifiEntry;
import com.android.wifitrackerlib.WifiPickerTracker;

import java.time.Clock;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;

/**
 * The Fragment sets up callback {@link NetworkRequestMatchCallback} with framework. To handle most
 * behaviors of the callback when requesting wifi network, except for error message. When error
 * happens, {@link NetworkRequestErrorDialogFragment} will be called to display error message.
 */
public class NetworkRequestDialogFragment extends NetworkRequestDialogBaseFragment implements
        DialogInterface.OnClickListener, WifiPickerTracker.WifiPickerTrackerCallback {

    private static final String TAG = "NetworkRequestDialogFragment";

    /**
     * Spec defines there should be 5 wifi ap on the list at most or just show all if {@code
     * mShowLimitedItem} is false.
     */
    private static final int MAX_NUMBER_LIST_ITEM = 5;
    private boolean mShowLimitedItem = true;

    @VisibleForTesting List<WifiEntry> mFilteredWifiEntries = new ArrayList<>();
    @VisibleForTesting List<ScanResult> mMatchedScanResults = new ArrayList<>();
    private WifiEntryAdapter mDialogAdapter;
    private NetworkRequestUserSelectionCallback mUserSelectionCallback;

    @VisibleForTesting WifiPickerTracker mWifiPickerTracker;
    // Worker thread used for WifiPickerTracker work.
    private HandlerThread mWorkerThread;
    // Max age of tracked WifiEntries.
    private static final long MAX_SCAN_AGE_MILLIS = 15_000;
    // Interval between initiating WifiPickerTracker scans.
    private static final long SCAN_INTERVAL_MILLIS = 10_000;

    public static NetworkRequestDialogFragment newInstance() {
        NetworkRequestDialogFragment dialogFragment = new NetworkRequestDialogFragment();
        return dialogFragment;
    }

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

        mWorkerThread = new HandlerThread(
                TAG + "{" + Integer.toHexString(System.identityHashCode(this)) + "}",
                Process.THREAD_PRIORITY_BACKGROUND);
        mWorkerThread.start();
        final Clock elapsedRealtimeClock = new SimpleClock(ZoneOffset.UTC) {
            @Override
            public long millis() {
                return SystemClock.elapsedRealtime();
            }
        };
        final Context context = getContext();
        mWifiPickerTracker = FeatureFactory.getFactory(context)
                .getWifiTrackerLibProvider()
                .createWifiPickerTracker(getSettingsLifecycle(), context,
                        new Handler(Looper.getMainLooper()),
                        mWorkerThread.getThreadHandler(),
                        elapsedRealtimeClock,
                        MAX_SCAN_AGE_MILLIS,
                        SCAN_INTERVAL_MILLIS,
                        this);
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final Context context = getContext();

        // Prepares title.
        final LayoutInflater inflater = LayoutInflater.from(context);
        final View customTitle = inflater.inflate(R.layout.network_request_dialog_title, null);

        final TextView title = customTitle.findViewById(R.id.network_request_title_text);
        title.setText(getTitle());
        final TextView summary = customTitle.findViewById(R.id.network_request_summary_text);
        summary.setText(getSummary());

        final ProgressBar progressBar = customTitle.findViewById(
                R.id.network_request_title_progress);
        progressBar.setVisibility(View.VISIBLE);

        // Prepares adapter.
        mDialogAdapter = new WifiEntryAdapter(context,
                R.layout.preference_access_point, mFilteredWifiEntries);

        final AlertDialog.Builder builder = new AlertDialog.Builder(context)
                .setCustomTitle(customTitle)
                .setAdapter(mDialogAdapter, this)
                .setNegativeButton(R.string.cancel, (dialog, which) -> onCancel(dialog))
                // Do nothings, will replace the onClickListener to avoid auto closing dialog.
                .setNeutralButton(R.string.network_connection_request_dialog_showall,
                        null /* OnClickListener */);

        // Clicking list item is to connect wifi ap.
        final AlertDialog dialog = builder.create();
        dialog.getListView().setOnItemClickListener(
                (parent, view, position, id) -> this.onClick(dialog, position));

        // Don't dismiss dialog when touching outside. User reports it is easy to touch outside.
        // This causes dialog to close.
        setCancelable(false);

        dialog.setOnShowListener((dialogInterface) -> {
            // Replace NeutralButton onClickListener to avoid closing dialog
            final Button neutralBtn = dialog.getButton(AlertDialog.BUTTON_NEUTRAL);
            neutralBtn.setVisibility(View.GONE);
            neutralBtn.setOnClickListener(v -> {
                mShowLimitedItem = false;
                updateWifiEntries();
                updateUi();
                neutralBtn.setVisibility(View.GONE);
            });
        });
        return dialog;
    }

    private BaseAdapter getDialogAdapter() {
        return mDialogAdapter;
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        if (mFilteredWifiEntries.size() == 0 || which >= mFilteredWifiEntries.size()) {
            return;  // Invalid values.
        }
        if (mUserSelectionCallback == null) {
            return; // Callback is missing or not ready.
        }

        final WifiEntry wifiEntry = mFilteredWifiEntries.get(which);
        WifiConfiguration config = wifiEntry.getWifiConfiguration();
        if (config == null) {
            config = WifiUtils.getWifiConfig(wifiEntry, null /* scanResult */);
        }
        mUserSelectionCallback.select(config);
    }

    @Override
    public void onCancel(@NonNull DialogInterface dialog) {
        super.onCancel(dialog);

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

    @Override
    public void onDestroy() {
        mWorkerThread.quit();

        super.onDestroy();
    }

    private void showAllButton() {
        final AlertDialog alertDialog = (AlertDialog) getDialog();
        if (alertDialog == null) {
            return;
        }

        final Button neutralBtn = alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL);
        if (neutralBtn != null) {
            neutralBtn.setVisibility(View.VISIBLE);
        }
    }

    private void hideProgressIcon() {
        final AlertDialog alertDialog = (AlertDialog) getDialog();
        if (alertDialog == null) {
            return;
        }

        final View progress = alertDialog.findViewById(R.id.network_request_title_progress);
        if (progress != null) {
            progress.setVisibility(View.GONE);
        }
    }

    /** Called when the state of Wifi has changed. */
    @Override
    public void onWifiStateChanged() {
        if (mMatchedScanResults.size() == 0) {
            return;
        }
        updateWifiEntries();
        updateUi();
    }

    /**
     * Update the results when data changes
     */
    @Override
    public void onWifiEntriesChanged() {
        if (mMatchedScanResults.size() == 0) {
            return;
        }
        updateWifiEntries();
        updateUi();
    }

    @Override
    public void onNumSavedSubscriptionsChanged() {
        // Do nothing.
    }

    @Override
    public void onNumSavedNetworksChanged() {
        // Do nothing.
    }

    @VisibleForTesting
    void updateWifiEntries() {
        final List<WifiEntry> wifiEntries = new ArrayList<>();
        if (mWifiPickerTracker.getConnectedWifiEntry() != null) {
            wifiEntries.add(mWifiPickerTracker.getConnectedWifiEntry());
        }
        wifiEntries.addAll(mWifiPickerTracker.getWifiEntries());

        mFilteredWifiEntries.clear();
        mFilteredWifiEntries.addAll(wifiEntries.stream().filter(entry -> {
            for (ScanResult matchedScanResult : mMatchedScanResults) {
                if (TextUtils.equals(entry.getSsid(), matchedScanResult.SSID)
                        && entry.getSecurity() == getWifiEntrySecurity(matchedScanResult)) {
                    return true;
                }
            }
            return false;
        }).limit(mShowLimitedItem ? MAX_NUMBER_LIST_ITEM : Long.MAX_VALUE)
                .collect(toList()));
    }

    private class WifiEntryAdapter extends ArrayAdapter<WifiEntry> {

        private final int mResourceId;
        private final LayoutInflater mInflater;

        WifiEntryAdapter(Context context, int resourceId, List<WifiEntry> objects) {
            super(context, resourceId, objects);
            mResourceId = resourceId;
            mInflater = LayoutInflater.from(context);
        }

        @Override
        public View getView(int position, View view, ViewGroup parent) {
            if (view == null) {
                view = mInflater.inflate(mResourceId, parent, false);

                final View divider = view.findViewById(
                        com.android.settingslib.R.id.two_target_divider);
                divider.setVisibility(View.GONE);
            }

            final WifiEntry wifiEntry = getItem(position);

            final TextView titleView = view.findViewById(android.R.id.title);
            if (titleView != null) {
                // Shows whole SSID for better UX.
                titleView.setSingleLine(false);
                titleView.setText(wifiEntry.getTitle());
            }

            final TextView summary = view.findViewById(android.R.id.summary);
            if (summary != null) {
                final String summaryString = wifiEntry.getSummary();
                if (TextUtils.isEmpty(summaryString)) {
                    summary.setVisibility(View.GONE);
                } else {
                    summary.setVisibility(View.VISIBLE);
                    summary.setText(summaryString);
                }
            }

            final PreferenceImageView imageView = view.findViewById(android.R.id.icon);
            final int level = wifiEntry.getLevel();
            if (imageView != null && level != WifiEntry.WIFI_LEVEL_UNREACHABLE) {
                final Drawable drawable = getContext().getDrawable(
                        Utils.getWifiIconResource(level));
                drawable.setTintList(
                        Utils.getColorAttr(getContext(), android.R.attr.colorControlNormal));
                imageView.setImageDrawable(drawable);
            }

            return view;
        }
    }

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

    @Override
    public void onMatch(List<ScanResult> scanResults) {
        mMatchedScanResults = scanResults;
        updateWifiEntries();
        updateUi();
    }

    @VisibleForTesting
    void updateUi() {
        // Update related UI buttons
        if (mShowLimitedItem && mFilteredWifiEntries.size() >= MAX_NUMBER_LIST_ITEM) {
            showAllButton();
        }
        if (mFilteredWifiEntries.size() > 0) {
            hideProgressIcon();
        }

        if (getDialogAdapter() != null) {
            getDialogAdapter().notifyDataSetChanged();
        }
    }
}
