package com.cerveza.togglefunction;

import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.location.LocationManager;
import android.media.AudioManager;
import android.net.ConnectivityManager;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.telephony.CellInfo;
import android.telephony.TelephonyManager;
import android.util.Log;

import com.cerveza.togglefunction.api.ControlFunction;
import com.cerveza.togglefunction.api.EMessageType;
import com.cerveza.togglefunction.api.MyWifiInfo;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Created by cerveza on 14/11/2016.
 */

public class FunctionChangeHandler {
    private Context context;
    private WifiManager wifiManager;
    private BluetoothManager bluetoothManager;
    private ConnectivityManager connectivityManager;
    private TelephonyManager telephonyManager;
    private LocationManager locationManager;
    private AudioManager audioManager;

    private static List<ControlFunction> actualControls;


    public FunctionChangeHandler(Context context) {
        if(actualControls == null){
            actualControls = SharedConstants.getFunctionControls();
        }

        this.context = context;

        wifiManager = (WifiManager) context.getSystemService(context.WIFI_SERVICE);
        bluetoothManager = (BluetoothManager) context.getSystemService(context.BLUETOOTH_SERVICE);
        connectivityManager = (ConnectivityManager) context.getSystemService(context.CONNECTIVITY_SERVICE);
        locationManager = (LocationManager) context.getSystemService(context.LOCATION_SERVICE);
        audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        telephonyManager = (TelephonyManager) context.getSystemService(context.TELEPHONY_SERVICE);
     }



    public void changeWifiStatus() {
        if (wifiManager.isWifiEnabled()) {
            wifiManager.setWifiEnabled(false);
        } else {
            wifiManager.setWifiEnabled(true);
        }
    }

    public void changeBluetoothState() {
        if (bluetoothManager.getAdapter().isEnabled()) {
            bluetoothManager.getAdapter().disable();
        } else {
            bluetoothManager.getAdapter().enable();
        }
    }

    public void changeMobileDataStatus() {
        try {
            final Class ConnectivityManagerClass = Class.forName(connectivityManager.getClass().getName());
            final Field iConnectivityManagerField = ConnectivityManagerClass.getDeclaredField("mService");
            iConnectivityManagerField.setAccessible(true);
            final Object iConnectivityManager = iConnectivityManagerField.get(connectivityManager);
            final Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName());
            final Method setMobileDataEnabledMethod = iConnectivityManagerClass.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
            setMobileDataEnabledMethod.setAccessible(true);

            Method getMobileDataEnabledMethod = ConnectivityManagerClass.getDeclaredMethod("getMobileDataEnabled");
            getMobileDataEnabledMethod.setAccessible(true);

            if (null != setMobileDataEnabledMethod) {
                if ((Boolean) getMobileDataEnabledMethod.invoke(connectivityManager)) {
                    setMobileDataEnabledMethod.invoke(iConnectivityManager, false);
                } else {
                    setMobileDataEnabledMethod.invoke(iConnectivityManager, true);
                }

            }
        } catch (Exception ex) {
            Log.e("Switch data status", "Error setting mobile data state", ex);
        }
    }

    public void changeGPSStatus() {
        Intent intent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }

    public void changeAudioStatus(){
        switch (audioManager.getRingerMode()){
            case AudioManager.RINGER_MODE_SILENT:
                audioManager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
                break;
            case AudioManager.RINGER_MODE_VIBRATE:
                audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
                break;
            case AudioManager.RINGER_MODE_NORMAL:
                audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
                break;
        }
    }

    public List<ControlFunction> checkFunctionStates() {
        boolean isDataEnabled = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isAvailable();
        boolean isWifiEnabled = wifiManager.isWifiEnabled();
        boolean isBluetoothEnabled = bluetoothManager.getAdapter().isEnabled();
        boolean isLocationEnable = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        int audioState = audioManager.getRingerMode();
        switch(audioState){
            case 1: audioState = 2; break;
            case 2: audioState = 1; break;
        }

        List<ControlFunction> controls = Arrays.asList(
                new ControlFunction(EMessageType.WIFI_CHANGE_STATUS, "WiFi", isWifiEnabled ? 1 : 0),
                new ControlFunction(EMessageType.BLUETOOTH_CHANGE_STATUS, "Bluetooth", isBluetoothEnabled ? 1 : 0),
                new ControlFunction(EMessageType.MOBILE_DATA_CHANGE_STATUS, "Mobile data", isDataEnabled ? 1 : 0),
                new ControlFunction(EMessageType.GPS_CHANGE_STATUS, "GPS", isLocationEnable? 1 : 0),
                new ControlFunction(EMessageType.AUDIO_CHANGE_STATUS, "Audio", audioState));
        return controls;
    }

    public List<ControlFunction> getUpdatedControls() {
        List<ControlFunction> newControls = checkFunctionStates();
        List<ControlFunction> differentControls = new ArrayList<>(newControls);
        differentControls.removeAll(actualControls);
        actualControls = newControls;
        return differentControls;
    }

    public MyWifiInfo getWifiInfo(){
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
        MyWifiInfo myWifiInfo = new MyWifiInfo(wifiInfo.getBSSID(),
                wifiInfo.getIpAddress(),wifiInfo.getLinkSpeed(),
                wifiInfo.getMacAddress(),wifiInfo.getRssi(),wifiInfo.getSSID());
        return myWifiInfo;
    }

    public CellInfo getCellularInfoOv(){
        List<CellInfo> cellInfos = telephonyManager.getAllCellInfo();   //This will give info of all sims present inside your mobile
        if(cellInfos!=null){
             return cellInfos.get(0);
            }
            return null;
    }

    public WifiInfo getWifiInfoOv(){
        return wifiManager.getConnectionInfo();
    }

    public void getBatteryInfo(){

    }

    /*
    @Override
    protected void onHandleIntent(Intent intent) {
        List<ControlFunction> controls;
        if (intent.getAction() == "WEARABLE_COMMAND") {
            switch ((EMessageType) intent.getExtras().get("MESSAGE_TYPE")) {
                case WIFI_CHANGE_STATUS:
                    changeWifiStatus();
                    break;
                case BLUETOOTH_CHANGE_STATUS:
                    changeBluetoothState();
                    break;
                case GPS_CHANGE_STATUS:
                    changeGPSStatus();
                    break;
                case MOBILE_DATA_CHANGE_STATUS:
                    changeMobileDataStatus();
                    break;
                case FUNCTIONS_STATE_SYNCHRONIZATION:
                    controls = getUpdatedControls();
                    if (controls.size() > 0) {
                        byte[] bytes = null;
                        try {
                            bytes = SerializeUtils.convertToBytes(controls);
                        } catch (IOException e) {
                            Log.e(this.getClass().getName(), "could not parse object to bytes", e);
                        }
                        Intent intentSendMessage = new Intent(this, MessageSendService.class).setAction("SEND_MESSAGE")
                                .putExtra("BYTES", bytes).putExtra("MESSAGE_TYPE", EMessageType.FUNCTIONS_STATE_SYNCHRONIZATION);
                        startService(intentSendMessage);
                    }
                    break;
                case FUNCTIONS_STATE_INITIALIZE:
                    resetControls();
                    controls = getUpdatedControls();
                    if (controls.size() > 0) {
                        byte[] bytes = null;
                        try {
                            bytes = SerializeUtils.convertToBytes(controls);
                        } catch (IOException e) {
                            Log.e(this.getClass().getName(), "could not parse object to bytes", e);
                        }
                        Intent intentSendMessage = new Intent(this, MessageSendService.class).setAction("SEND_MESSAGE")
                                .putExtra("BYTES", bytes).putExtra("MESSAGE_TYPE", EMessageType.FUNCTIONS_STATE_INITIALIZE);
                        startService(intentSendMessage);
                    }
                    break;
                case GET_WIFI_INFO:
                    WifiInfo wifiInfo = wifiManager.getConnectionInfo();
                    MyWifiInfo myWifiInfo = new MyWifiInfo(wifiInfo.getBSSID(),
                            wifiInfo.getIpAddress(),wifiInfo.getLinkSpeed(),
                            wifiInfo.getMacAddress(),wifiInfo.getRssi(),wifiInfo.getSSID());

                    byte[] bytes = null;
                    try {
                        bytes = SerializeUtils.convertToBytes(myWifiInfo);
                    } catch (IOException e) {
                        Log.e(this.getClass().getName(), "could not parse object to bytes", e);
                    }
                    Intent intentSendMessage = new Intent(this, MessageSendService.class).setAction("SEND_MESSAGE")
                            .putExtra("BYTES", bytes).putExtra("MESSAGE_TYPE", EMessageType.GET_WIFI_INFO);
                    startService(intentSendMessage);
                    break;

            }
        }
    }*/

    public void resetControls(){
        for (ControlFunction control: actualControls) {
            control.setDefaultState();
        }
    }

}
