package com.mobify.astro.plugins.webviewplugin;

import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.webkit.CookieManager;
import android.webkit.WebSettings;
import android.webkit.WebView;

import com.mobify.astro.BuildConfig;
import com.mobify.astro.PermissionsInterface;
import com.mobify.astro.utilities.AstroWebUtilities;

public class AstroWebView extends WebView {
    final private int Y_SCROLL_THRESHOLD = 20;

    AstroWebViewClient astroWebViewClient;
    AstroWebChromeClient astroWebChromeClient;

    private Float firstTouchX;
    private Float firstTouchY;

    private boolean scrollEnabled = true;

    public AstroWebView(Context context) {
        super(context);

        astroWebChromeClient = new AstroWebChromeClient((PermissionsInterface) context);
        setWebChromeClient(astroWebChromeClient);

        getSettings().setJavaScriptEnabled(true);
        getSettings().setDomStorageEnabled(true);
        getSettings().setAppCacheEnabled(true);
        getSettings().setDatabaseEnabled(true);
        getSettings().setGeolocationEnabled(true);

        if (BuildConfig.DEBUG && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        }

        AstroWebUtilities.addAstroUserAgent(context, getSettings());

        CookieManager cookieManager = CookieManager.getInstance();
        cookieManager.setAcceptFileSchemeCookies(true);
        if (android.os.Build.VERSION.SDK_INT >= 21) {
            // Without this, cookies on the domains of third party assets (scripts, etc) will not
            // get sent with the request for that asset.
            cookieManager.setAcceptThirdPartyCookies(this, true);
        }
    }

    public void setAstroWebViewClient(AstroWebViewClient astroWebViewClient) {
        setWebViewClient(astroWebViewClient);
        this.astroWebViewClient = astroWebViewClient;
    }

    public AstroWebViewClient getAstroWebViewClient() {
        return astroWebViewClient;
    }

    public void setScrollBarVisibility(boolean visible) {
        this.setVerticalScrollBarEnabled(visible);
        this.setHorizontalScrollBarEnabled(visible);
    }

    public void setScrolling(boolean scrollEnabled) {
        this.scrollEnabled = scrollEnabled;
        final boolean enabled = scrollEnabled;
        final Activity activity = (Activity)getContext();

        // Ensure we're running on the UIThread so tests don't break
        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                int inputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
                if (enabled) {
                    inputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
                }
                activity.getWindow().setSoftInputMode(inputMode);
            }
        });
    }

    public boolean isScrollEnabled() {
        return this.scrollEnabled;
    }

    @Override
    public boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY,
            int scrollRangeX, int scrollRangeY, int maxOverScrollX,
            int maxOverScrollY, boolean isTouchEvent) {

        if (scrollEnabled) {
            return super.overScrollBy(deltaX, deltaY, scrollX, scrollY,
                    scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
        }
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        float currentX = ev.getX();
        float currentY = ev.getY();

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                // When the user touches the WebView, store the X and Y coordinates.
                firstTouchX = currentX;
                firstTouchY = currentY;
                break;

            case MotionEvent.ACTION_MOVE:
                boolean isScrollingRight = firstTouchX - currentX > 0;
                boolean isScrollingLeft = firstTouchX - currentX < 0;
                boolean canScrollLeft = this.canScrollHorizontally(-1);
                boolean canScrollRight = this.canScrollHorizontally(1);
                float deltaY = Math.abs(currentY - firstTouchY);

                // Stop propagation of events to the parent under the following conditions:
                // - If we are currently scrolling right but we haven't reached the end of the
                //   right hand side of the WebView. This will stop views (such as the DrawerLayout)
                //   from taking over touch events when we still want users to be able to scroll in
                //   the WebView. Same goes for when scrolling left but haven't reached the end of
                //   the left hand side of the WebView.
                // - If the distance the user has scrolled is greater then the accepted threshold.
                if ((isScrollingRight && canScrollRight) ||
                        (isScrollingLeft && canScrollLeft) ||
                        (deltaY > Y_SCROLL_THRESHOLD)) {
                    this.requestDisallowInterceptTouchEvent(true);
                }
                break;

            case MotionEvent.ACTION_UP:
                // When the user finishes touching in the WebView, clear the X and Y coordinates.
                firstTouchX = null;
                firstTouchY = null;
                break;
        }

        return super.onTouchEvent(ev);
    }
}
