package com.xypower.common;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Handler;
import androidx.annotation.RequiresApi;
import android.util.Log;

import androidx.annotation.RequiresApi;

import com.android.dx.stock.ProxyBuilder;

import java.io.File;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;


public class HotspotManager {



    @RequiresApi(api = Build.VERSION_CODES.O)
    public static class OreoWifiManager {
        private static final String TAG = OreoWifiManager.class.getSimpleName();

        private Context mContext;
        private WifiManager mWifiManager;
        private ConnectivityManager mConnectivityManager;

        public OreoWifiManager(Context c) {
            mContext = c;
            mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
            mConnectivityManager = (ConnectivityManager) mContext.getSystemService(ConnectivityManager.class);
        }

        /**
         * This sets the Wifi SSID and password
         * Call this before {@code startTethering} if app is a system/privileged app
         * Requires: android.permission.TETHER_PRIVILEGED which is only granted to system apps
         */
        public void configureHotspot(String name, String password) {
            WifiConfiguration apConfig = new WifiConfiguration();
            apConfig.SSID = name;
            apConfig.preSharedKey = password;
            apConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
            try {
                Method setConfigMethod = mWifiManager.getClass().getMethod("setWifiApConfiguration", WifiConfiguration.class);
                boolean status = (boolean) setConfigMethod.invoke(mWifiManager, apConfig);
                Log.d(TAG, "setWifiApConfiguration - success? " + status);
            } catch (Exception e) {
                Log.e(TAG, "Error in configureHotspot");
                e.printStackTrace();
            }
        }

        /**
         * Checks where tethering is on.
         * This is determined by the getTetheredIfaces() method,
         * that will return an empty array if not devices are tethered
         *
         * @return true if a tethered device is found, false if not found
         */
    /*public boolean isTetherActive() {
        try {
            Method method = mConnectivityManager.getClass().getDeclaredMethod("getTetheredIfaces");
            if (method == null) {
                Log.e(TAG, "getTetheredIfaces is null");
            } else {
                String res[] = (String[]) method.invoke(mConnectivityManager, null);
                Log.d(TAG, "getTetheredIfaces invoked");
                Log.d(TAG, Arrays.toString(res));
                if (res.length > 0) {
                    return true;
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "Error in getTetheredIfaces");
            e.printStackTrace();
        }
        return false;
    }
*/
        /**
         * This enables tethering using the ssid/password defined in Settings App>Hotspot & tethering
         * Does not require app to have system/privileged access
         * Credit: Vishal Sharma - https://stackoverflow.com/a/52219887
         */
        public boolean startTethering(final OnStartTetheringCallback callback) {

            // On Pie if we try to start tethering while it is already on, it will
            // be disabled. This is needed when startTethering() is called programmatically.
        /*if (isTetherActive()) {
            Log.d(TAG, "Tether already active, returning");
            return false;
        }*/

            File outputDir = mContext.getCodeCacheDir();
            Object proxy;
            try {
                proxy = ProxyBuilder.forClass(OnStartTetheringCallbackClass())
                        .dexCache(outputDir).handler(new InvocationHandler() {
                            @Override
                            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                                switch (method.getName()) {
                                    case "onTetheringStarted":
                                        callback.onTetheringStarted();
                                        break;
                                    case "onTetheringFailed":
                                        callback.onTetheringFailed();
                                        break;
                                    default:
                                        ProxyBuilder.callSuper(proxy, method, args);
                                }
                                return null;
                            }

                        }).build();
            } catch (Exception e) {
                Log.e(TAG, "Error in enableTethering ProxyBuilder");
                e.printStackTrace();
                return false;
            }

            Method method = null;
            try {
                method = mConnectivityManager.getClass().getDeclaredMethod("startTethering", int.class, boolean.class, OnStartTetheringCallbackClass(), Handler.class);
                if (method == null) {
                    Log.e(TAG, "startTetheringMethod is null");
                } else {
                    method.invoke(mConnectivityManager, ConnectivityManager.TYPE_MOBILE, false, proxy, null);
                    Log.d(TAG, "startTethering invoked");
                }
                return true;
            } catch (Exception e) {
                Log.e(TAG, "Error in enableTethering");
                e.printStackTrace();
            }
            return false;
        }

        public void stopTethering() {
            try {
                Method method = mConnectivityManager.getClass().getDeclaredMethod("stopTethering", int.class);
                if (method == null) {
                    Log.e(TAG, "stopTetheringMethod is null");
                } else {
                    method.invoke(mConnectivityManager, ConnectivityManager.TYPE_MOBILE);
                    Log.d(TAG, "stopTethering invoked");
                }
            } catch (Exception e) {
                Log.e(TAG, "stopTethering error: " + e.toString());
                e.printStackTrace();
            }
        }

        private Class OnStartTetheringCallbackClass() {
            try {
                return Class.forName("android.net.ConnectivityManager$OnStartTetheringCallback");
            } catch (ClassNotFoundException e) {
                Log.e(TAG, "OnStartTetheringCallbackClass error: " + e.toString());
                e.printStackTrace();
            }
            return null;
        }
    }

    public static abstract class OnStartTetheringCallback {
        /**
         * Called when tethering has been successfully started.
         */
        public abstract void onTetheringStarted();

        /**
         * Called when starting tethering failed.
         */
        public abstract void onTetheringFailed();

    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    private static void setHotspotOnPhone(Context mContext, boolean isEnable) {

        OreoWifiManager mTestOreoWifiManager = null;

        if (mTestOreoWifiManager ==null) {
            mTestOreoWifiManager = new OreoWifiManager(mContext);
        }


        if (isEnable){
            OnStartTetheringCallback callback = new OnStartTetheringCallback() {
                @Override
                public void onTetheringStarted() {
                }

                @Override
                public void onTetheringFailed() {

                }
            };

            mTestOreoWifiManager.startTethering(callback);
        }else{
            mTestOreoWifiManager.stopTethering();
        }

    }

    /*
    public static void setWiFiApEnable(Context context, boolean isEnable) {
        ConnectivityManager mConnectivityManager= (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (isEnable) {
            mConnectivityManager.startTethering(ConnectivityManager.TETHERING_WIFI, false, new ConnectivityManager.OnStartTetheringCallback() {
                @Override
                public void onTetheringStarted() {
                    Log.d(TAG, "onTetheringStarted");
                    // Don't fire a callback here, instead wait for the next update from wifi.
                }

                @Override
                public void onTetheringFailed() {
                    Log.d(TAG, "onTetheringFailed");
                    // TODO: Show error.
                }
            });
        } else {
            mConnectivityManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
        }
    }

     */

    public static void enableHotspot(Context context, boolean isEnable) {
        // R: Adnroid 11
        // O: Android 8
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // Android 11
            setHotspotOnPhone(context, isEnable);
        }/* else if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // Android 8

        }
        */
    }
}
