/*
 * Copyright 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.managedprovisioning.task;

import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiManager;
import android.text.TextUtils;

import java.lang.Thread;

import com.android.managedprovisioning.NetworkMonitor;
import com.android.managedprovisioning.ProvisionLogger;
import com.android.managedprovisioning.WifiConfig;

/**
 * Adds a wifi network to system.
 */
public class AddWifiNetworkTask implements NetworkMonitor.Callback {
    private static final int RETRY_SLEEP_DURATION_BASE_MS = 500;
    private static final int RETRY_SLEEP_MULTIPLIER = 2;
    private static final int MAX_RETRIES = 6;

    private final Context mContext;
    private final String mSsid;
    private final boolean mHidden;
    private final String mSecurityType;
    private final String mPassword;
    private final String mProxyHost;
    private final int mProxyPort;
    private final String mProxyBypassHosts;
    private final String mPacUrl;
    private final Callback mCallback;

    private WifiManager mWifiManager;
    private NetworkMonitor mNetworkMonitor;
    private WifiConfig mWifiConfig;

    private int mDurationNextSleep = RETRY_SLEEP_DURATION_BASE_MS;
    private int mRetriesLeft = MAX_RETRIES;

    public AddWifiNetworkTask(Context context, String ssid, boolean hidden, String securityType,
            String password, String proxyHost, int proxyPort, String proxyBypassHosts,
            String pacUrl, Callback callback) {
        mCallback = callback;
        mContext = context;
        mSsid = ssid;
        mHidden = hidden;
        mSecurityType = securityType;
        mPassword = password;
        mProxyHost = proxyHost;
        mProxyPort = proxyPort;
        mProxyBypassHosts = proxyBypassHosts;
        mPacUrl = pacUrl;
        mWifiManager  = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
        mWifiConfig = new WifiConfig(mWifiManager);
    }

    public void run() {
        if (!enableWifi()) {
            ProvisionLogger.loge("Failed to enable wifi");
            mCallback.onError();
            return;
        }

        mNetworkMonitor = new NetworkMonitor(mContext, this);

        if (!isConnectedToWifi(mContext)) {
            if (TextUtils.isEmpty(mSsid)) {
                ProvisionLogger.loge("Wifi is supposed to be setup in activity," +
                        " or a valid wifi ssid has to be specified.");
                mCallback.onError();
                return;
            }

            connectToProvidedNetwork();
        } else {
            mCallback.onSuccess();
        }
    }

    private void connectToProvidedNetwork() {
        int netId = mWifiConfig.addNetwork(mSsid, mHidden, mSecurityType, mPassword, mProxyHost,
                mProxyPort, mProxyBypassHosts, mPacUrl);

        if (netId == -1) {
            ProvisionLogger.loge("Failed to save network.");
            if (mRetriesLeft > 0) {
                ProvisionLogger.loge("Retrying in " + mDurationNextSleep + " ms.");
                try {
                    Thread.sleep(mDurationNextSleep);
                } catch (InterruptedException e) {
                    ProvisionLogger.loge("Retry interrupted.");
                }
                mDurationNextSleep *= RETRY_SLEEP_MULTIPLIER;
                mRetriesLeft--;
                connectToProvidedNetwork();
                return;
            } else {
                ProvisionLogger.loge("Already retried " +  MAX_RETRIES + " times."
                        + " Quit retrying and report error.");
                mCallback.onError();
                return;
            }
        } else {
            if (!mWifiManager.reconnect()) {
                ProvisionLogger.loge("Unable to connect to wifi");
                mCallback.onError();
                return;
            }
        }

        // NetworkMonitor will call onNetworkConnected when in Wifi mode.
    }

    private boolean enableWifi() {
        if (mWifiManager != null) {
            int wifiState = mWifiManager.getWifiState();
            boolean wifiOn = wifiState == WifiManager.WIFI_STATE_ENABLED;
            if (!wifiOn) {
                if (!mWifiManager.setWifiEnabled(true)) {
                    return false;
                } else {
                    return true;
                }
            } else {
                return true;
            }
        } else {
            return false;
        }
    }

    @Override
    public void onNetworkConnected() {
        if (NetworkMonitor.isConnectedToWifi(mContext) &&
                mWifiManager.getConnectionInfo().getSSID().equals(mSsid)) {
            ProvisionLogger.logd("Connected to the correct network");
            mNetworkMonitor.close();
            mNetworkMonitor = null;
            mCallback.onSuccess();
        }
    }

    @Override
    public void onNetworkDisconnected() {

    }

    public void cleanUp() {
        if (mNetworkMonitor != null) {
            mNetworkMonitor.close();
            mNetworkMonitor = null;
        }
    }

    public static boolean isConnectedToWifi(Context context) {
        ConnectivityManager cm =
                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
        return info.isConnected();
    }

    public static Intent getWifiPickIntent() {
        Intent wifiIntent = new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK);
        wifiIntent.putExtra("only_access_points", true);
        wifiIntent.putExtra("extra_prefs_show_button_bar", true);
        wifiIntent.putExtra("wifi_enable_next_on_connect", true);
        return wifiIntent;
    }

    public abstract static class Callback {
        public abstract void onSuccess();
        public abstract void onError();
    }
}
