package cc.winboll.studio.webpagesources.common;

import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.net.http.SslError;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.DownloadListener;
import android.webkit.HttpAuthHandler;
import android.webkit.JavascriptInterface;
import android.webkit.SslErrorHandler;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.view.GestureDetectorCompat;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.webpagesources.MainActivity;
import cc.winboll.studio.webpagesources.R;
import cc.winboll.studio.webpagesources.thread.LinkDownLoadThread;
import cc.winboll.studio.webpagesources.util.UIUtil;
import cc.winboll.studio.webpagesources.view.ItemLongClickedPopWindow;
import com.hjq.toast.ToastUtils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class BaseWebView extends WebView {

    public static final String TAG = "BaseWebView";

    public static final int WEB_CopyLink = 0;
    public static final int WEB_DownLoadLink = 1;

    protected Context mContext;
    static String _mszLastUrl = "";
    IOnPageFinished mIOnPageFinished;
    protected MyWebChromeClient mMyWebChromeClient;
    protected BaseWebViewClient mBaseWebViewClient;
    protected BaseWebViewHandler mBaseWebViewHandler;
    private int downX, downY;
    private GestureDetectorCompat mGestureDetector;
    ValueCallback<Uri[]> mFilePathCallback;
    WebChromeClient.FileChooserParams mFileChooserParams;

    AuthLoginDialog mAuthLoginDialog;

    public BaseWebView(Context context) {
        super(context);
    }

    public BaseWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;

        mBaseWebViewHandler = new BaseWebViewHandler();
        MyWebChromeClient mMyWebChromeClient = new MyWebChromeClient();
        setWebChromeClient(mMyWebChromeClient);
        mBaseWebViewClient = new BaseWebViewClient();
        setWebViewClient(mBaseWebViewClient);

        WebSettings mWebSettings = getSettings();

        // ------------------- 优化后的 WebSettings 配置 -------------------
        // 基础功能配置
        mWebSettings.setJavaScriptEnabled(true);                          // 启用JavaScript
        mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true);      // 允许JS打开新窗口
        mWebSettings.setDomStorageEnabled(true);                         // 启用DOM存储
        mWebSettings.setDatabaseEnabled(true);                           // 启用数据库存储
        //mWebSettings.setAppCacheEnabled(true);                           // 启用应用缓存
        String appCachePath = context.getCacheDir().getAbsolutePath();
        //mWebSettings.setAppCachePath(appCachePath);
        mWebSettings.setCacheMode(WebSettings.LOAD_DEFAULT);              // 缓存模式

        // 页面渲染与缩放
        mWebSettings.setUseWideViewPort(true);                           // 支持viewport标签
        mWebSettings.setLoadWithOverviewMode(true);                      // 自动加载时适应屏幕
        mWebSettings.setSupportZoom(true);                               // 支持缩放
        mWebSettings.setBuiltInZoomControls(true);                       // 显示缩放控件
        mWebSettings.setDisplayZoomControls(false);                      // 隐藏默认缩放控件
        mWebSettings.setDefaultTextEncodingName("utf-8");                // 默认编码
        mWebSettings.setMinimumFontSize(12);                             // 最小字体大小

        // 性能优化
        mWebSettings.setLoadsImagesAutomatically(true);                  // 自动加载图片
        mWebSettings.setBlockNetworkImage(false);                        // 不阻止图片加载
        mWebSettings.setRenderPriority(WebSettings.RenderPriority.HIGH); // 高渲染优先级

        // 混合内容配置（Android 5.0+）
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            mWebSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        }

        // 安全配置
        mWebSettings.setSafeBrowsingEnabled(true);                       // 启用安全浏览
        mWebSettings.setAllowFileAccess(true);                           // 允许访问文件URL
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            mWebSettings.setAllowFileAccessFromFileURLs(false);          // 禁止文件URL访问其他文件
            mWebSettings.setAllowUniversalAccessFromFileURLs(false);     // 禁止文件URL执行JS
        }

        // 高级功能（可选）
        mWebSettings.setGeolocationEnabled(true);                        // 启用地理位置
        mWebSettings.setNeedInitialFocus(true);                          // 获取初始焦点
        mWebSettings.setSaveFormData(true);                              // 保存表单数据
        mWebSettings.setEnableSmoothTransition(true);                    // 平滑过渡动画

        // 硬件加速（Android 3.0+）
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            setLayerType(View.LAYER_TYPE_HARDWARE, null);
        }

        // 字体缩放（100%为默认）
        mWebSettings.setTextZoom(100);
        // ------------------- WebSettings 配置结束 -------------------

        mWebSettings.setSafeBrowsingEnabled(true);
        addJavascriptInterface(new JSConsole(mContext), "console");
        addJavascriptInterface(new JS(mContext), "local_obj");

        setInitialScale(60);

        mGestureDetector = new GestureDetectorCompat(mContext, new GestureDetector.SimpleOnGestureListener() {
                @Override
                public void onLongPress(MotionEvent e) {
                    downX = (int) e.getX();
                    downY = (int) e.getY();
                }
            });

        setOnLongClickListener(new View.OnLongClickListener() {
                String szUrl = "";
                @Override
                public boolean onLongClick(View v) {

                    WebView.HitTestResult result = ((WebView)v).getHitTestResult();
                    if (null == result) 
                        return false;
                    int type = result.getType();
                    if (type == WebView.HitTestResult.UNKNOWN_TYPE) 
                        return false;
                    if (type == WebView.HitTestResult.EDIT_TEXT_TYPE) {
                    }
                    final ItemLongClickedPopWindow itemLongClickedPopWindow = new ItemLongClickedPopWindow(mContext, ItemLongClickedPopWindow.IMAGE_VIEW_POPUPWINDOW, UIUtil.dip2px(mContext, 180), ViewGroup.LayoutParams.WRAP_CONTENT);

                    szUrl = result.getExtra();

                    itemLongClickedPopWindow.showAtLocation(v, Gravity.TOP | Gravity.LEFT, downX, downY + 10);

                    itemLongClickedPopWindow.getView(R.id.item_longclicked_copylink)
                        .setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
                                ClipData clip = ClipData.newPlainText("simple text", szUrl);
                                clipboard.setPrimaryClip(clip);
                                Toast.makeText(mContext, "Copy to clipboard.", Toast.LENGTH_SHORT).show();
                                itemLongClickedPopWindow.dismiss();
                            }
                        });
                    itemLongClickedPopWindow.getView(R.id.item_longclicked_downloadlink)
                        .setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                itemLongClickedPopWindow.dismiss();
                                new Thread(new LinkDownLoadThread(szUrl)).start();
                            }
                        });
                    return true;
                }
            });
    }

    public BaseWebView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public String getLastUrl() {
        return _mszLastUrl;
    }

    @Override
    public void loadUrl(String url) {
        MainActivity.postStatusBarMessage(String.format("正在加载：%s", url));
        Pattern patternHttp = Pattern.compile("(?i)^http[s]{0,1}://", Pattern.CASE_INSENSITIVE);
        Matcher matcherHttp = patternHttp.matcher(url);
        if (matcherHttp.matches()) {
            stopLoading();
            loadUrl(url);
            return;
        } else {
            Pattern pattern = Pattern.compile("^[a-z]+:.*", Pattern.MULTILINE);
            Matcher matcher = pattern.matcher(url);
            if (matcher.find()) {
                super.loadUrl(url);
                return;
            } 
        }
    }

    public void setFilePathCallback(ValueCallback<Uri[]> mFilePathCallback) {
        this.mFilePathCallback = mFilePathCallback;
    }

    public ValueCallback<Uri[]> getFilePathCallback() {
        return mFilePathCallback;
    }

    public void setFileChooserParams(WebChromeClient.FileChooserParams mFileChooserParams) {
        this.mFileChooserParams = mFileChooserParams;
    }

    public WebChromeClient.FileChooserParams getFileChooserParams() {
        return mFileChooserParams;
    }

    private class MyWebChromeClient extends WebChromeClient {
        @Override
        public void onProgressChanged(WebView view, int newProgress) {
        }

        @Override
        public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
            setFilePathCallback(filePathCallback);
            setFileChooserParams(fileChooserParams);
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.setType("*/*");
            ((AppCompatActivity)mContext).startActivityForResult(intent, MainActivity.REQUEST_FILE_CHOOSER);
            return true;
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean ret = mGestureDetector.onTouchEvent(event);
        LogUtils.d(TAG, String.format("onTouchEvent ret : %s", ret));

        return super.onTouchEvent(event);
    }

    class BaseWebViewHandler extends Handler {

        public static final String TAG = "BaseWebViewHandler";

        public static final int MSG_RELOAD_LOG = 0X100;
        public static final int MSG_SHOW_DATA = 0X123;

        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_SHOW_DATA:{
                        loadDataWithBaseURL("", (String)msg.obj, "text/html", "UTF-8", "");
                        break;
                    }
            }
            super.handleMessage(msg);
        }
    }

    final class InJavaScriptLocalObj {
        @JavascriptInterface
        public void getSource(String html) {
        }
    }

    public class MyDownLoadListener implements DownloadListener {
        private Context mContext;

        public MyDownLoadListener(Context context) {
            this.mContext = context;
        }

        @Override
        public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
            Uri uri = Uri.parse(url);
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            mContext.startActivity(intent);
        }
    }

    class BaseWebViewClient extends WebViewClient {

        public static final String TAG = "BaseWebViewClient";

        @Override
        public void onPageFinished(WebView view, String url) {
            view.loadUrl("javascript:window.local_obj.showSource('<head>'+" +
                         "document.getElementsByTagName('html')[0].innerHTML+'</head>');");
            super.onPageFinished(view, url);
            mIOnPageFinished.onPageFinished(url);
            LogUtils.d(TAG, "Page load finished : " + url);
            _mszLastUrl = url;
            MainActivity.postStatusBarMessage(String.format("加载完成：%s", url));
        }

        @Override
        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
            //SSL证书错误修复方法：
            //网站证书下载网站是https://www.ssleye.com/ssltool/certs_down.html
            //使用该网站访问要获取证书的主机
            //获取证书后导出证书到 res/raw/<标识名称>.cer
            //再在res/xml/network_security_config.xml配置网站证书设置。
            ToastUtils.show("SSL证书错误!");
            LogUtils.d(TAG, "SSL证书错误! onReceivedSslError 0\nerror : " + error.toString());
        }

        @Override
        public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
            int statusCode = errorResponse.getStatusCode();
            LogUtils.d(TAG, "onReceivedHttpError statusCode " + Integer.toString(statusCode));
            super.onReceivedHttpError(view, request, errorResponse);
        }

        @Override
        public void onReceivedError(WebView view, int errorCode,
                                    String description, String failingUrl) {
            super.onReceivedError(view, errorCode, description, failingUrl);
            LogUtils.d(TAG, "onReceivedError 1\nerrorCode : " + errorCode
                       + "\ndescription :" + description + "\nfailingUrl : " + failingUrl);
        }

        @Override
        public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
            super.onReceivedError(view, request, error);
            LogUtils.d(TAG, "onReceivedError 2\nUrl : " + request.getUrl()
                       + "\nErrorCode : " + error.getErrorCode()
                       + "\nDescription : " + error.getDescription());
        }

        @Override
        public void onReceivedLoginRequest(WebView view, String realm, String account, String args) {
            super.onReceivedLoginRequest(view, realm, account, args);
            LogUtils.d(TAG, "onReceivedLoginRequest");
        }

        @Override
        public void onLoadResource(WebView view, String url) {
            super.onLoadResource(view, url);
        }

        @Override
        public void onReceivedHttpAuthRequest(WebView view,
                                              HttpAuthHandler handler, String host, String realm) {
            mAuthLoginDialog = new AuthLoginDialog(view, handler,  host, realm);
            mAuthLoginDialog.show();
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            LogUtils.d(TAG, "Page load started : " + url);
            _mszLastUrl = url;
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
            // 修复Android 5.0点击无反应的问题
            view.loadUrl(request.getUrl().toString());
            return true;
        }
    }

    public interface IOnPageFinished {
        void onPageFinished(String url);
    }

    public void setOnPageFinished(IOnPageFinished iOnPageFinished) {
        mIOnPageFinished = iOnPageFinished;
    }
}

