package org.wikipedia.util;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
import android.util.Log;

import org.wikipedia.R;
import org.wikipedia.WikipediaApp;
import org.wikipedia.page.PageTitle;
import org.wikipedia.settings.Prefs;
import org.wikipedia.zero.WikipediaZeroHandler;

import java.net.URLDecoder;

import static org.wikipedia.zero.WikipediaZeroHandler.showZeroExitInterstitialDialog;

public final class UriUtil {

    /**
     * Decodes a URL-encoded string into its UTF-8 equivalent.
     * @param url The URL-encoded string that you wish to decode.
     * @return The decoded string, or the input string if the decoding failed.
     */
    @NonNull public static String decodeURL(@NonNull String url) {
        try {
            return URLDecoder.decode(url, "UTF-8");
        } catch (Exception e) {
            // Swallow any exception, including UnsupportedEncodingException (shouldn't happen),
            // and IllegalArgumentException (can happen with malformed encoding), and just return
            // the original string.
            Log.d("Wikipedia", "URL decoding failed. String was: " + url);
            return url;
        }
    }

    /**
     * Open the specified URI in an external browser (even if our app's intent filter
     * matches the given URI)
     *
     * @param context Context of the calling app
     * @param uri URI to open in an external browser
     */
    public static void visitInExternalBrowser(final Context context, Uri uri) {
        Intent chooserIntent = ShareUtil.createChooserIntent(new Intent(Intent.ACTION_VIEW, uri),
                null, context);
        if (chooserIntent == null) {
            // This means that there was no way to handle this link.
            // We will just show a toast now. FIXME: Make this more visible?
            ShareUtil.showUnresolvableIntentMessage(context);
        } else {
            context.startActivity(chooserIntent);
        }
    }

    /**
     * Resolves a potentially protocol relative URL to a 'full' URL
     *
     * @param url Url to check for (and fix) protocol relativeness
     * @return A fully qualified, protocol specified URL
     */
    public static String resolveProtocolRelativeUrl(String url) {
        return (url.startsWith("//") ? WikipediaApp.getInstance().getWikiSite().scheme() + ":" + url
                : url);
    }

    public static boolean isValidPageLink(@NonNull Uri uri) {
        return (!TextUtils.isEmpty(uri.getAuthority())
                && uri.getAuthority().endsWith("wikipedia.org")
                && !TextUtils.isEmpty(uri.getPath())
                && uri.getPath().startsWith("/wiki"));
    }

    public static void handleExternalLink(final Context context, final Uri uri) {
        final WikipediaZeroHandler zeroHandler = WikipediaApp.getInstance()
                .getWikipediaZeroHandler();

        if (!zeroHandler.isZeroEnabled()) {
            if (!StringUtil.emptyIfNull(zeroHandler.getXCarrier()).equals("")) {
                // User is potentially zero-rated based on IP, but not on a whitelisted wiki (this
                // is rare)
                zeroHandler.getZeroFunnel().logExtLink();
            }
            visitInExternalBrowser(context, uri);
            return;
        }

        if (!Prefs.isShowZeroInterstitialEnabled()) {
            visitInExternalBrowser(context, uri);
            zeroHandler.getZeroFunnel().logExtLinkAuto();
            return;
        }

        showZeroExitInterstitialDialog(context, uri);
    }

    public static void sendGeoIntent(@NonNull Activity activity,
                                     @NonNull Location location,
                                     String placeName) {
        String geoStr = "geo:";
        geoStr += Double.toString(location.getLatitude()) + ","
                + Double.toString(location.getLongitude());
        if (!TextUtils.isEmpty(placeName)) {
            geoStr += "?q=" + Uri.encode(placeName);
        }
        try {
            activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(geoStr)));
        } catch (ActivityNotFoundException e) {
            FeedbackUtil.showMessage(activity, R.string.error_no_maps_app);
        }
    }

    public static String getUrlWithProvenance(Context context, PageTitle title,
                                              @StringRes int provId) {
        return title.getCanonicalUri() + "?wprov=" + context.getString(provId);
    }

    /**
     * Note that while this method also replaces '_' with spaces it doesn't fully decode the string.
     */
    @NonNull
    public static String getTitleFromUrl(@NonNull String url) {
        return removeFragment(removeLinkPrefix(url)).replace("_", " ");
    }

    /** For internal links only */
    @NonNull
    public static String removeInternalLinkPrefix(@NonNull String link) {
        return link.replaceFirst("/wiki/", "");
    }

    /** For links that could be internal or external links */
    @NonNull
    private static String removeLinkPrefix(@NonNull String link) {
        return link.replaceFirst("^.*?/wiki/", "");
    }

    /** Removes an optional fragment portion of a URL */
    @VisibleForTesting
    @NonNull
    static String removeFragment(@NonNull String link) {
        return link.replaceFirst("#.*$", "");
    }

    public static String getFragment(String link) {
        return Uri.parse(link).getFragment();
    }

    private UriUtil() {

    }
}

@@ -397,33 +397,8 @@
 ils;
-%0Aimport android.util.Log;
 %0A%0Aim
@@ -528,16 +528,49 @@
 .Prefs;%0A
+import org.wikipedia.util.log.L;%0A
 import o
@@ -606,24 +606,69 @@
 roHandler;%0A%0A
+import java.io.UnsupportedEncodingException;%0A
 import java.
@@ -871,16 +871,89 @@
 ivalent.
+ If the string cannot be decoded, the%0A     * original string is returned.
 %0A     * 
@@ -1252,119 +1252,37 @@
 ch (
-Exception e) %7B%0A            // Swallow any exception, including UnsupportedEncodingException (shouldn't happen),
+IllegalArgumentException e) %7B
 %0A   
@@ -1293,19 +1293,23 @@
      // 
-and
+Swallow
  Illegal
@@ -1372,23 +1372,16 @@
 and just
- return
 %0A       
@@ -1387,16 +1387,23 @@
       //
+ return
  the ori
@@ -1433,26 +1433,11 @@
    L
-og
 .d(
-%22Wikipedia%22, 
 %22URL
@@ -1500,16 +1500,110 @@
 rn url;%0A
+        %7D catch (UnsupportedEncodingException e) %7B%0A            throw new RuntimeException(e);%0A
         

make Uri Exception handling more granular