package com.step.upon;

import android.content.Context;
import android.content.Intent;
import android.net.DhcpInfo;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.net.Uri;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.List;
import com.step.upon.LameEngine;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaResourceApi;
import org.apache.cordova.*;

import org.apache.cordova.PermissionHelper;
import android.Manifest;

import java.io.File;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import java.security.Permission;


import java.util.ArrayList;

import com.step.upon.RecorderUtility;
import com.step.upon.FileUtility;
import com.step.upon.FileProvider;

import static org.apache.cordova.media.AudioHandler.PERMISSION_DENIED_ERROR;


public class upon extends CordovaPlugin {

    public static String [] permissions = { Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_COARSE_LOCATION};

    public static int RECORD_AUDIO = 0;
    public static int WRITE_EXTERNAL_STORAGE = 1;
    public static int ACCESS_COARSE_LOCATION= 2;

    private CallbackContext messageChannel;
    private RecorderUtility utility = null;
    private FileUtility fileUtility = null;

	@Override
    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
        super.initialize(cordova, webView);
    }


    @Override
    public boolean execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException {
		if (action.equals("requestPermision")) { //申请权限
            this.messageChannel = callbackContext;
            promptForPerssion();

        } else if (action.equals("requestLocalPermision")) {
            this.messageChannel = callbackContext;
            promptForLocalPerssion();

        } else if (action.equals("mp3ToWav")) {
         	PluginResult result = new PluginResult(PluginResult.Status.OK,"success");
            callbackContext.sendPluginResult(result);
            return true;

        } else if (action.equals("amrToWav")) {
            PluginResult result = new PluginResult(PluginResult.Status.OK, "success");
            callbackContext.sendPluginResult(result);
            return true;

        } else if (action.equals("startWavRecord")) {
            this.messageChannel = callbackContext;
            this.utility = null;
            this.utility = new RecorderUtility();

            String filePath = args.getString(0).trim();
            if (filePath.length() == 0) {
                PluginResult result = new PluginResult(PluginResult.Status.ERROR, "File name Empty");
                callbackContext.sendPluginResult(result);
                return false;
            }

            boolean ret = this.utility.startWavRecord(filePath);
            if (ret) {
                PluginResult result = new PluginResult(PluginResult.Status.OK, "Recorder start success");
                callbackContext.sendPluginResult(result);
                return true;

            } else {
                PluginResult result = new PluginResult(PluginResult.Status.ERROR, "Record start Failed");
                callbackContext.sendPluginResult(result);
                return true;
            }

        } else if (action.equals("stopWavRecord")) {
            boolean ret = this.utility.stopWavRecord();

            if (ret) {
                PluginResult result = new PluginResult(PluginResult.Status.OK, "recorder stop success");
                callbackContext.sendPluginResult(result);

            } else {
                PluginResult result = new PluginResult(PluginResult.Status.ERROR, "recorder stop error");
                callbackContext.sendPluginResult(result);
            }

            return true;

        } else if (action.equals("jniTest")) {
            String info = LameEngine.jniTest();
            PluginResult result = new PluginResult(PluginResult.Status.OK, info);
            callbackContext.sendPluginResult(result);
            return true;

        } else if (action.equals("getHotSpotInfo")) {
            Boolean isWifiAPEnable = false;
            JSONObject hotspotInfo = null;

            try {
                WifiManager manager = (WifiManager) cordova.getActivity().getApplicationContext().getSystemService(Context.WIFI_SERVICE);

                Method get_wifi_ap_state = manager.getClass().getDeclaredMethod("getWifiApState");
                int state = Integer.parseInt(String.valueOf(get_wifi_ap_state.invoke(manager)));

                Field field = manager.getClass().getDeclaredField("WIFI_AP_STATE_ENABLED");
                int value = Integer.parseInt(String.valueOf(field.get(manager)));

                if (state == value) {
                    hotspotInfo = new JSONObject();

                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                        hotspotInfo.put("ssid" , "");
                        hotspotInfo.put("bssid", "");
                    } else {
                        Method get_wifi_ap_config = manager.getClass().getDeclaredMethod("getWifiApConfiguration");
                        WifiConfiguration configuration = (WifiConfiguration) get_wifi_ap_config.invoke(manager);

                        hotspotInfo.put("ssid" , configuration.SSID);
                        hotspotInfo.put("bssid", configuration.BSSID);
                    }

                    hotspotInfo.put("localIp" , getLocalIpAddress());

                    isWifiAPEnable = true;
                }
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }

            if (isWifiAPEnable) {
                PluginResult result = new PluginResult(PluginResult.Status.OK, hotspotInfo);
                callbackContext.sendPluginResult(result);
            } else {
                PluginResult result = new PluginResult(PluginResult.Status.ERROR, hotspotInfo);
                callbackContext.sendPluginResult(result);
            }

            return true;
        } else if (action.equals("trimWav")) {
            this.fileUtility = null;
            this.fileUtility = new FileUtility();
            String path = args.getString(0).trim();
            String name = args.getString(1).trim();
            int offset = Integer.parseInt(args.getString(2).trim());
            int size = Integer.parseInt(args.getString(3).trim());

            if (path.length() == 0 || name.length() == 0) {
                PluginResult result = new PluginResult(PluginResult.Status.ERROR, "file name or path is empty");
                callbackContext.sendPluginResult(result);
                return false;
            }

            if (size < 1) {
                PluginResult result = new PluginResult(PluginResult.Status.ERROR, "trim file size error");
                callbackContext.sendPluginResult(result);
                return false;
            }

            PluginResult result = new PluginResult(PluginResult.Status.OK,this.fileUtility.trimWAV(path, name, offset, size));
            callbackContext.sendPluginResult(result);
            return true;
        } else if (action.equals("getMP3InfoList")) {
            if (this.fileUtility == null) {
                this.fileUtility = new FileUtility();
            }
            PluginResult result = new PluginResult(PluginResult.Status.OK,this.fileUtility.getMp3InfoList(cordova.getActivity().getApplicationContext()));
            callbackContext.sendPluginResult(result);
            return true;
        } else if (action.equals("open")) {
            String fileUrl = args.getString(0).trim();
            String contentType = args.getString(1).trim();

            Log.d("wangjun", "open fileUrl is " + fileUrl);
            Log.d("wangjun", "open contentType is " + contentType);

            this.messageChannel = callbackContext;
            openAPK(fileUrl, contentType);
        } else {
         	callbackContext.error("Can not find the function");
            return false;
        }

        return true;
    }

    public void onRequestPermissionResult(int requestCode, String[] permissions,
                                          int[] grantResults) throws JSONException
    {
        for(int r:grantResults) {
            if(r == PackageManager.PERMISSION_DENIED) {
                this.messageChannel.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, PERMISSION_DENIED_ERROR));
                return;
            }
        }

        this.promptForPerssion();
    }


    protected void getWritePermission(int requestCode) {
        PermissionHelper.requestPermission(this, requestCode, permissions[WRITE_EXTERNAL_STORAGE]);
    }


    protected void getMicPermission(int requestCode) {
        PermissionHelper.requestPermission(this, requestCode, permissions[RECORD_AUDIO]);
    }


    protected void getLocationPermission(int requestCode) {
        PermissionHelper.requestPermission(this, requestCode, permissions[ACCESS_COARSE_LOCATION]);
    }


    private void promptForLocalPerssion() {
        if (!PermissionHelper.hasPermission(this, permissions[ACCESS_COARSE_LOCATION])) {
            getLocationPermission(ACCESS_COARSE_LOCATION);
        } else {
            this.messageChannel.sendPluginResult(new PluginResult(PluginResult.Status.OK, "success"));
        }
    }


    private void promptForPerssion()
    {
        if(PermissionHelper.hasPermission(this, permissions[WRITE_EXTERNAL_STORAGE])
            && PermissionHelper.hasPermission(this, permissions[RECORD_AUDIO])
            && PermissionHelper.hasPermission(this, permissions[ACCESS_COARSE_LOCATION])) {
            this.messageChannel.sendPluginResult(new PluginResult(PluginResult.Status.OK, "success"));
        } else if (!PermissionHelper.hasPermission(this, permissions[ACCESS_COARSE_LOCATION])) {
            getLocationPermission(ACCESS_COARSE_LOCATION);
        } else if(!PermissionHelper.hasPermission(this, permissions[RECORD_AUDIO])) {
            getMicPermission(RECORD_AUDIO);
        } else if(!PermissionHelper.hasPermission(this, permissions[WRITE_EXTERNAL_STORAGE])){
            getWritePermission(WRITE_EXTERNAL_STORAGE);
        }
    }


    private String getLocalIpAddress() {
        try{
            Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
            while(en.hasMoreElements()) {
                NetworkInterface nif = en.nextElement();
                Enumeration<InetAddress> enumIpAddr = nif.getInetAddresses();
                while(enumIpAddr.hasMoreElements()) {
                    InetAddress mInetAddress = enumIpAddr.nextElement();
                    if(!mInetAddress.isLoopbackAddress() && mInetAddress instanceof Inet4Address) {
                        return mInetAddress.getHostAddress();
                    }
                }
            }
        } catch(SocketException ex) {
            Log.e("wangjun", "获取本地IP地址失败");
        }

        return null;
    }

    private void openAPK(String fileArg, String contentType) throws JSONException {
        String fileName = "";
        try {
            CordovaResourceApi resourceApi = webView.getResourceApi();
            Uri fileUri = resourceApi.remapUri(Uri.parse(fileArg));
            fileName = stripFileProtocol(fileUri.toString());
        } catch (Exception e) {
            fileName = fileArg;
        }
        File file = new File(fileName);
        if (file.exists()) {
            try {
                Uri path = Uri.fromFile(file);
                Intent intent = new Intent(Intent.ACTION_VIEW);
                if((Build.VERSION.SDK_INT >= 23 && !contentType.equals("application/vnd.android.package-archive"))
                    || (Build.VERSION.SDK_INT >= 24 && contentType.equals("application/vnd.android.package-archive"))) {
                    Context context = cordova.getActivity().getApplicationContext();
                    path = FileProvider.getUriForFile(context, cordova.getActivity().getPackageName() + ".provider", file);
                    intent.setDataAndType(path, contentType);
                    intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
                    //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

                    List<ResolveInfo> infoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
                    for (ResolveInfo resolveInfo : infoList) {
                        String packageName = resolveInfo.activityInfo.packageName;
                        context.grantUriPermission(packageName, path, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    }
                } else {
                    intent.setDataAndType(path, contentType);
                    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                }
                cordova.getActivity().startActivity(intent);
                this.messageChannel.sendPluginResult(new PluginResult(PluginResult.Status.OK, "success"));
            } catch (android.content.ActivityNotFoundException e) {
                this.messageChannel.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, "open apk faild 1"));
            }
        } else {
            this.messageChannel.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, "open apk failed 2"));
        }
    }

    private String stripFileProtocol(String uriString) {
        if (uriString.startsWith("file://")) {
            uriString = uriString.substring(7);
        } else if (uriString.startsWith("content://")) {
            uriString = uriString.substring(10);
        }
        return uriString;
    }

}
