package com.erakk.lnreader.helper;

import android.content.Intent;
import android.net.Uri;
import android.preference.PreferenceManager;
import android.util.Log;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.erakk.lnreader.Constants;
import com.erakk.lnreader.LNReaderApplication;
import com.erakk.lnreader.R;
import com.erakk.lnreader.UIHelper;
import com.erakk.lnreader.dao.NovelsDao;
import com.erakk.lnreader.model.PageModel;
import com.erakk.lnreader.ui.activity.DisplayImageActivity;
import com.erakk.lnreader.ui.activity.DisplayLightNovelContentActivity;

import java.lang.ref.WeakReference;

public class BakaTsukiWebViewClient extends WebViewClient {
    private static final String TAG = BakaTsukiWebViewClient.class.toString();
    protected WeakReference<DisplayLightNovelContentActivity> activityRef;
    private boolean hasError = false;
    private boolean scaleChangedRunnablePending = false;

    private boolean isExternalNeedSave = true;

    public BakaTsukiWebViewClient(DisplayLightNovelContentActivity caller) {
        super();
        this.activityRef = new WeakReference<DisplayLightNovelContentActivity>(caller);
    }

    public void setExternalNeedSave(boolean value) {
        synchronized (this) {
            isExternalNeedSave = value;
        }
    }

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        Log.d(TAG, "Try handling: " + url);
        hasError = false;
        final DisplayLightNovelContentActivity caller = activityRef.get();
        if (caller == null)
            return false;

        if (view.canGoBack())
            caller.setLastReadState();

        Log.i(TAG, "Handling: " + url);

        if (url.contains("title=File:")) {
            handleImageLinkActivity(url, caller);
        } else if (url.startsWith("wyciwyg://") || url.startsWith("cid:frame-")) {
            // ignore wyciwyg:// protocol
            // ignore cid:frame-, refer to issue #246
            return true;
        } else {
            boolean isHandled = handleInternalPage(view, url, caller);

            if (!isHandled) {
                boolean useInternalWebView = PreferenceManager.getDefaultSharedPreferences(caller).getBoolean(Constants.PREF_USE_INTERNAL_WEBVIEW, false);
                if (useInternalWebView) {
                    // set intent to external page
                    caller.getIntent().removeExtra(Constants.EXTRA_PAGE);
                    caller.getIntent().putExtra(Constants.EXTRA_PAGE, Util.SanitizeBaseUrl(url, false));
                    caller.getIntent().removeExtra(Constants.EXTRA_PAGE_IS_EXTERNAL);
                    caller.getIntent().putExtra(Constants.EXTRA_PAGE_IS_EXTERNAL, true);

                    // check if the same page and trying to load anchor link.
                    // need to handle if page use urlParams to do navigation.
                    if (url.contains("#")) {
                        String currUrl = Util.SanitizeBaseUrl(view.getUrl(), false);
                        String[] urlParts = url.split("#", 2);
                        String[] urlQuery = urlParts[0].split("\\?", 2);
                        if (!Util.isStringNullOrEmpty(currUrl) && currUrl.startsWith(urlQuery[0])) {
                            if (urlParts.length == 2)
                                view.loadUrl("javascript:window.location.hash=" + urlParts[1] + ";");
                        }
                    } else {
                        // don't sanitize the url due to redirect issue
                        PageModel pageModel = new PageModel();
                        pageModel.setPage(url);
                        pageModel.setExternal(true);
                        PageModel temp = pageModel;
                        try {
                            temp = NovelsDao.getInstance().getExistingPageModel(pageModel, null);
                        } catch (Exception e) {
                            Log.e(TAG, "Failed to get pageModel: " + url, e);
                        }
                        if (temp != null)
                            pageModel = temp;

                        Log.i(TAG, "Loading external url: " + pageModel.getPage());
                        caller.loadExternalUrl(pageModel, false);
                    }
                } else {
                    // set the intent page to the current page
                    caller.getIntent().removeExtra(Constants.EXTRA_PAGE);
                    if (caller.content != null)
                        caller.getIntent().putExtra(Constants.EXTRA_PAGE, caller.content.getPage());
                    else
                        caller.getIntent().putExtra(Constants.EXTRA_PAGE, caller.getIntent().getStringExtra(Constants.EXTRA_PAGE));
                    caller.getIntent().removeExtra(Constants.EXTRA_PAGE_IS_EXTERNAL);
                    caller.getIntent().putExtra(Constants.EXTRA_PAGE_IS_EXTERNAL, false);

                    // use default handler.
                    caller.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
                }
            }
        }

        return true;
    }

    /**
     * check if internal and load it
     *
     * @param view
     * @param url
     * @param caller
     * @return true if internal page is loaded successfully.
     */
    private boolean handleInternalPage(WebView view, String url, DisplayLightNovelContentActivity caller) {
        if (url.contains("/project/index.php?title=")) {
            try {
                String titles[] = url.split("title=", 2);
                if (titles.length == 2 && !(titles[1].length() == 0)) {
                    // split anchor text
                    String[] titles2 = titles[1].split("#", 2);

                    // check if load different page.
                    synchronized (caller.content) {
                        String currentPage = caller.content.getPage();
                        if (!currentPage.equalsIgnoreCase(titles2[0])) {
                            Log.d(TAG, "Got different page name: " + titles2[0]);
                            PageModel tempPage = new PageModel();
                            tempPage.setPage(titles2[0]);
                            PageModel pageModel = NovelsDao.getInstance().getExistingPageModel(tempPage, null);
                            if (pageModel != null) {
                                caller.jumpTo(pageModel);
                                Log.d(TAG, "Loading : " + pageModel.getPage());
                            } else {
                                Log.w(TAG, "PageModel not downloaded yet, most likely not listed in chapter list: " + titles2[0]);
                                tempPage.setTitle(titles2[0]);
                                tempPage.setParent(currentPage);
                                tempPage.setType(PageModel.TYPE_CONTENT);
                                NovelsDao.getInstance().updatePageModel(tempPage);
                                caller.jumpTo(tempPage);
                            }
                        } else
                            Log.d(TAG, "Already loaded: " + currentPage);

                        // navigate to the anchor if exist.
                        if (titles2.length == 2) {
                            view.loadUrl("#" + titles2[1]);
                        }
                    }
                    return true;
                } else
                    Log.w(TAG, "Unknown format for internal url: " + url);
            } catch (Exception e) {
                Log.e(TAG, "Failed to load: " + url, e);
            }
        }
        return false;
    }

    private void handleImageLinkActivity(String url, DisplayLightNovelContentActivity caller) {
        Intent intent = new Intent(caller, DisplayImageActivity.class);
        intent.putExtra(Constants.EXTRA_IMAGE_URL, url);
        intent.putExtra("image_list", caller.content.getBigImages());
        intent.putExtra(Constants.EXTRA_PAGE, caller.content.getPage());
        caller.startActivity(intent);
    }

    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);
        final DisplayLightNovelContentActivity caller = activityRef.get();
        if (caller != null && !hasError) {
            NonLeakingWebView wv = (NonLeakingWebView) caller.findViewById(R.id.webViewContent);
            String page = caller.getIntent().getStringExtra(Constants.EXTRA_PAGE);

            // assumption all external page is start with http
            // and ignore for internal pages which loaded with base url to bakatsuki.org
            if (url.startsWith("http") && !url.startsWith(UIHelper.getBaseUrl(view.getContext()))) {
                if (!isExternalNeedSave || !getAllowSaveExternal()) {
                    Log.d(TAG, "Skip auto save for: " + page + " " + !isExternalNeedSave + " " + !getAllowSaveExternal());
                    return;
                }
                wv.saveMyWebArchive(url);
            }
        }
    }

    private boolean getAllowSaveExternal() {
        return PreferenceManager.getDefaultSharedPreferences(LNReaderApplication.getInstance()).getBoolean(Constants.PREF_SAVE_EXTERNAL_URL, true);
    }

    @Override
    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
        super.onReceivedError(view, errorCode, description, failingUrl);
        hasError = true;
        Log.w(TAG, String.format("Error detected: [%s] %s => %s", errorCode, description, failingUrl));
    }

    /**
     * KitKat chromium text zoom handler, see http://stackoverflow.com/a/20000193
     *
     * @param webView
     * @param oldScale
     * @param newScale
     */
    @Override
    public void onScaleChanged(final WebView webView, float oldScale, float newScale) {
        if (UIHelper.getKitKatWebViewFix(webView.getContext())) {
            if (scaleChangedRunnablePending) {
                Log.d(TAG, "OnScaleChange KitKat handler already running");
                return;
            }
            synchronized (webView) {
                scaleChangedRunnablePending = true;
                webView.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        webView.loadUrl("javascript:recalcWidth();", null);
                        scaleChangedRunnablePending = false;
                    }
                }, UIHelper.getIntFromPreferences(Constants.PREF_KITKAT_WEBVIEW_FIX_DELAY, 500));
            }
        }
    }
}
