package allen.town.podcast.view;

import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

import androidx.core.content.ContextCompat;
import androidx.core.util.Consumer;

import allen.town.focus_common.util.TopSnackbarUtil;
import allen.town.podcast.R;
import allen.town.podcast.activity.MainActivity;
import allen.town.podcast.core.util.menuhandler.MenuItemUtils;
import allen.town.podcast.core.util.Converter;
import allen.town.podcast.core.util.IntentUtils;
import allen.town.podcast.core.util.NetworkUtils;
import allen.town.podcast.core.util.ShareUtils;
import allen.town.podcast.core.util.playback.Timeline;
import me.zhanghai.android.fastscroll.FastScrollWebView;

public class PodWebView extends WebView implements View.OnLongClickListener {
    private static final String TAG = "PodWebView";

    /**
     * URL that was selected via long-press.
     */
    private String selectedUrl;
    private Consumer<Integer> timecodeSelectedListener;
    private Runnable pageFinishedListener;

    public PodWebView(Context context) {
        super(context);
        setup();
    }

    public PodWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setup();
    }

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

    private void setup() {
        setBackgroundColor(Color.TRANSPARENT);
        if (!NetworkUtils.networkAvailable()) {
            getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
            // Use cached resources, even if they have expired
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        }
        getSettings().setUseWideViewPort(false);
        getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
        getSettings().setLoadWithOverviewMode(true);
        setOnLongClickListener(this);

        setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                if (Timeline.isTimecodeLink(url) && timecodeSelectedListener != null) {
                    timecodeSelectedListener.accept(Timeline.getTimecodeLinkTime(url));
                } else {
                    IntentUtils.openInBrowser(getContext(), url);
                }
                return true;
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                Log.d(TAG, "page finished");
                if (pageFinishedListener != null) {
                    pageFinishedListener.run();
                }
            }
        });
    }

    @Override
    public boolean onLongClick(View v) {
        WebView.HitTestResult r = getHitTestResult();
        if (r != null && r.getType() == WebView.HitTestResult.SRC_ANCHOR_TYPE) {
            selectedUrl = r.getExtra();
            showContextMenu();
            return true;
        } else if (r != null && r.getType() == HitTestResult.EMAIL_TYPE) {
            ClipboardManager clipboardManager = ContextCompat.getSystemService(this.getContext(),
                                                                               ClipboardManager.class);
            if (clipboardManager != null) {
                clipboardManager.setPrimaryClip(ClipData.newPlainText("FocusPodcast", r.getExtra()));
            }
            if (this.getContext() instanceof MainActivity) {
                if (Build.VERSION.SDK_INT <= 32) {
                    TopSnackbarUtil.showSnack(this.getContext(), getResources().getString(R.string.copied_to_clipboard), Toast.LENGTH_SHORT);
                }
            }
            return true;
        }
        selectedUrl = null;
        return false;
    }

    public boolean onContextItemSelected(MenuItem item) {
        if (selectedUrl == null) {
            return false;
        }

        final int itemId = item.getItemId();
        if (itemId == R.id.open_in_browser_item) {
            IntentUtils.openInBrowser(getContext(), selectedUrl);
        } else if (itemId == R.id.share_url_item) {
            ShareUtils.shareLink(getContext(), selectedUrl);
        } else if (itemId == R.id.copy_url_item) {
            ClipData clipData = ClipData.newPlainText(selectedUrl, selectedUrl);
            ClipboardManager cm = (ClipboardManager) getContext()
                    .getSystemService(Context.CLIPBOARD_SERVICE);
            cm.setPrimaryClip(clipData);
            TopSnackbarUtil.showSnack(this.getContext(),R.string.copied_url_msg, Toast.LENGTH_LONG);
        } else if (itemId == R.id.go_to_position_item) {
            if (Timeline.isTimecodeLink(selectedUrl) && timecodeSelectedListener != null) {
                timecodeSelectedListener.accept(Timeline.getTimecodeLinkTime(selectedUrl));
            } else {
                Log.e(TAG, "Selected go_to_position_item, but URL was no timecode link: " + selectedUrl);
            }
        } else {
            selectedUrl = null;
            return false;
        }
        selectedUrl = null;
        return true;
    }

    @Override
    protected void onCreateContextMenu(ContextMenu menu) {
        super.onCreateContextMenu(menu);
        if (selectedUrl == null) {
            return;
        }

        if (Timeline.isTimecodeLink(selectedUrl)) {
            menu.add(Menu.NONE, R.id.go_to_position_item, Menu.NONE, R.string.go_to_position_label);
            menu.setHeaderTitle(Converter.getDurationStringLong(Timeline.getTimecodeLinkTime(selectedUrl)));
        } else {
            Uri uri = Uri.parse(selectedUrl);
            final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            if (IntentUtils.isCallable(getContext(), intent)) {
                menu.add(Menu.NONE, R.id.open_in_browser_item, Menu.NONE, R.string.open_in_browser_label);
            }
            menu.add(Menu.NONE, R.id.copy_url_item, Menu.NONE, R.string.copy_url_label);
            menu.add(Menu.NONE, R.id.share_url_item, Menu.NONE, R.string.share_url_label);
            menu.setHeaderTitle(selectedUrl);
        }
        MenuItemUtils.setOnClickListeners(menu, this::onContextItemSelected);
    }

    public void setTimecodeSelectedListener(Consumer<Integer> timecodeSelectedListener) {
        this.timecodeSelectedListener = timecodeSelectedListener;
    }

    public void setPageFinishedListener(Runnable pageFinishedListener) {
        this.pageFinishedListener = pageFinishedListener;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(Math.max(getMeasuredWidth(), getMinimumWidth()),
                Math.max(getMeasuredHeight(), getMinimumHeight()));
    }
}
