package com.nsgk.ruralWeb.web;

import android.app.Activity;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.os.Handler;
import android.util.Log;
import android.webkit.JavascriptInterface;
import android.webkit.ValueCallback;
import android.webkit.WebView;
import android.widget.Toast;

import androidx.core.app.ActivityCompat;

import com.nsgk.ruralWeb.FullscreenActivity;
import com.nsgk.ruralWeb.enums.NSEnums;
import com.nsgk.ruralWeb.location.NSLocationInfo;
import com.nsgk.ruralWeb.location.NSAMapLocation;
import com.nsgk.ruralWeb.location.NSRealtimeLocation;
import com.nsgk.ruralWeb.location.NSSystemLocation;
import com.nsgk.ruralWeb.sys.NSConstants;
import com.nsgk.ruralWeb.sys.NSPreference;
import com.nsgk.ruralWeb.utils.NSContextUtils;

public class NSEnvWindowObject
{
    private static final String ID_TAG = NSEnvWindowObject.class.getName();
    private static final String FUSED_PROVIDER = "fused";

    private final Handler m_handler;
    private final Context m_context;
    private final WebView m_webView;

    private final NSSystemLocation location;

    private final NSAMapLocation     amapLocation;
    private final NSRealtimeLocation realtimeLocation;
    private final NSPreference       preference;
    // 最近一次获取到的定位坐标, 如果获取定位失败则返回此值. 可能不需要, 因为PASSIVE_PROVIDER就为最近的定位
    private       String         lastLocation = null;

    public NSEnvWindowObject(Context context, Handler handler, WebView webView)
    {
        m_context = context;
        m_handler = handler;
        m_webView = webView;
        location = new NSSystemLocation(m_context);
        amapLocation = new NSAMapLocation(m_context);
        realtimeLocation = new NSRealtimeLocation(m_context);
        preference = new NSPreference(m_context);
    }

    public void OnDestroy()
    {
        if(amapLocation.IsInitialized())
            amapLocation.Shutdown();
        if(realtimeLocation.IsInitialized())
            realtimeLocation.Shutdown();
    }

    @JavascriptInterface
    public void Toast(final String message)
    {
        ShowToast(message, Toast.LENGTH_LONG);
    }

    private void ShowToast(final String message, int duration)
    {
        RunOnUIThread(new Runnable() {
            @Override
            public void run()
            {
                Toast.makeText(m_context, message, duration).show();
            }
        });
    }

    @JavascriptInterface
    public void Log(final String message)
    {
        Log.i(ID_TAG, message);
    }

    @JavascriptInterface
    public String GetLocation(final String type)
    {
        Log.d(ID_TAG, "Web线程: " + Thread.currentThread().getId());

        if(!CheckLocationPermission())
        {
            return lastLocation;
        }

        NSLocationInfo loc;
        String location = preference.GetString(NSPreference.LOCATION_SCHEME, NSConstants.DEFAULT_LOCATION_SCHEME);
        String provider = preference.GetString(NSPreference.LOCATION_PROVIDER, NSConstants.DEFAULT_LOCATION_PROVIDER);
        Log.d(ID_TAG, "定位提供器: " + provider);
        switch(location)
        {
            case NSEnums.LocationScheme.GAODE:
                loc = GetAMapLocation();
                if(null == loc)
                    loc = GetBuiltInLocation(provider);
                break;
            case NSEnums.LocationScheme.REALTIME:
                loc = GetRealtimeLocation();
                if(null == loc)
                    loc = GetBuiltInLocation(provider);
                break;
            case NSEnums.LocationScheme.SYSTEM:
            default:
                loc = GetBuiltInLocation(provider);
                break;
        }

        return SetLastLocation(loc);
    }

    private String ReturnLocation(NSLocationInfo loc)
    {
        return loc.longitude + "," + loc.latitude;
    }

    private String SetLastLocation(NSLocationInfo loc)
    {
        if(null != loc)
            lastLocation = ReturnLocation(loc);
        return lastLocation;
    }

    private NSLocationInfo GetBuiltInLocation(String type)
    {
        Log.i(ID_TAG, "使用系统定位");
        NSLocationInfo loc = null;
        try
        {
            long start = System.currentTimeMillis();
            loc = location.GetLocation(type);
            long end = System.currentTimeMillis();
            Log.i(ID_TAG, "系统定位结果: " + loc + ", 耗时=" + (end - start) + "毫秒");
        }
        catch(Throwable e)
        {
            e.printStackTrace();
        }
        return loc;
    }

    private NSLocationInfo GetRealtimeLocation()
    {
        Log.i(ID_TAG, "使用系统实时定位");
        NSLocationInfo loc = null;
        try
        {
            NSPreference preference = new NSPreference(m_context);
            if(!realtimeLocation.IsInitialized())
            {
                realtimeLocation.SetOption(NSRealtimeLocation.OPTION_MIN_TIME, preference.GetIntFromString(NSPreference.LOCATION_REALTIME_INTERVAL, NSConstants.DEFAULT_LOCATION_REALTIME_INTERVAL));
                realtimeLocation.SetOption(NSRealtimeLocation.OPTION_MIN_DISTANCE, preference.GetIntFromString(NSPreference.LOCATION_REALTIME_DISTANCE, NSConstants.DEFAULT_LOCATION_REALTIME_DISTANCE));
                int flag = NSRealtimeLocation.DEFAULT_FLAG | NSRealtimeLocation.FLAG_BUILTIN_THREAD;
                String provider = preference.GetString(NSPreference.LOCATION_PROVIDER, NSConstants.DEFAULT_LOCATION_PROVIDER);
                if(LocationManager.GPS_PROVIDER.equals(provider))
                {
                    flag &= ~NSRealtimeLocation.FLAG_PRIORITY_NETWORK;
                    flag |= NSRealtimeLocation.FLAG_PRIORITY_GPS;
                }
                realtimeLocation.Init(flag);
            }
            long start = System.currentTimeMillis();
            loc = realtimeLocation.Read(preference.GetIntFromString(NSPreference.LOCATION_REALTIME_READ_COUNT, NSConstants.DEFAULT_LOCATION_REALTIME_READ_COUNT));
            long end = System.currentTimeMillis();
            Log.i(ID_TAG, "系统实时定位结果: " + loc + ", 耗时=" + (end - start) + "毫秒");
        }
        catch(Throwable e)
        {
            e.printStackTrace();
        }
        return loc;
    }

    public NSLocationInfo GetAMapLocation()
    {
        Log.i(ID_TAG, "使用高德定位");
        NSLocationInfo loc = null;
        try
        {
            NSPreference preference = new NSPreference(m_context);
            if(!amapLocation.IsInitialized())
            {
                amapLocation.SetOption(NSAMapLocation.OPTION_INTERVAL, preference.GetIntFromString(NSPreference.LOCATION_GAODE_INTERVAL, NSConstants.DEFAULT_LOCATION_GAODE_INTERVAL));
                amapLocation.Init(NSAMapLocation.DEFAULT_FLAG | NSAMapLocation.FLAG_BUILTIN_THREAD);
            }
            long start = System.currentTimeMillis();
            loc = amapLocation.Read(preference.GetIntFromString(NSPreference.LOCATION_GAODE_READ_COUNT, NSConstants.DEFAULT_LOCATION_GAODE_READ_COUNT));
            long end = System.currentTimeMillis();
            Log.i(ID_TAG, "高德定位结果: " + loc + ", 耗时=" + (end - start) + "毫秒");
        }
        catch(Throwable e)
        {
            e.printStackTrace();
        }
        return loc;
    }

    private boolean CheckLocationPermission()
    {
        if(ActivityCompat.checkSelfPermission(m_context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(m_context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
        {
            Activity activity = (Activity) m_context;

            if (activity.shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION) && activity.shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_COARSE_LOCATION)) // do not ask
            {
                Toast.makeText(m_context, "请先允许定位服务", Toast.LENGTH_LONG).show();
                NSContextUtils.RequestLocationPermission(activity, FullscreenActivity.PERMISSION_LOCATION_REQUEST_CODE);
            }
            else
            {
                activity.requestPermissions(new String[] { Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION }, FullscreenActivity.PERMISSION_LOCATION_REQUEST_CODE);
            }

            return false;
        }
        else
            return true;
    }

    protected void RunOnUIThread(Runnable runnable)
    {
        if(null != m_handler)
            m_handler.post(runnable);
        else if(m_context instanceof Activity)
            ((Activity)m_context).runOnUiThread(runnable);
        else
        {
            Log.e(ID_TAG, "无法在UI线程中执行");
        }
    }

    protected void CallJSFunc(final String func, Object...args)
    {
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < args.length; i++)
        {
            sb.append("'").append(args[i].toString()).append("'");
            if(i < args.length - 1)
                sb.append(", ");
        }
        final String arg = sb.toString();
        RunOnUIThread(new Runnable() {
            @Override
            public void run()
            {
                String script = "javascript:typeof(" + func + ") == 'function' && " + func + "(" + arg + ");";
                Log.e(ID_TAG, String.format("调用js函数: 函数(%s), 参数(%s)", func, arg));
                m_webView.evaluateJavascript(script, new ValueCallback<String>() {
                    @Override
                    public void onReceiveValue(String value) {
                        Log.e(ID_TAG, String.format("js函数 %s 返回: %s", func, value));
                    }
                });
            }
        });
    }

    protected void CallJSFunc_beforeAndroid4_4(final String func, Object...args)
    {
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < args.length; i++)
        {
            sb.append("'").append(args[i].toString()).append("'");
            if(i < args.length - 1)
                sb.append(", ");
        }
        final String arg = sb.toString();
        RunOnUIThread(new Runnable() {
            @Override
            public void run() {
                Log.e(ID_TAG, String.format("调用js函数: 函数(%s), 参数(%s)", func, arg));
                String script = "javascript:typeof(" + func + ") == 'function' && " + func + "(" + arg + ");";
                Log.e(ID_TAG, script);
                m_webView.loadUrl(script, null);
            }
        });
    }
}