/*
 * Copyright (C) 2017 Hazuki
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package jp.hazuki.yuzubrowser.utils;

import android.net.Uri;
import android.text.TextUtils;

import java.net.IDN;

public class UrlUtils {

    public static String decodeUrl(String url) {
        if (url == null) return null;
        return decodeUrl(Uri.parse(url));
    }

    public static String decodeUrl(Uri uri) {
        Uri.Builder decode = uri.buildUpon();
        if (isValid(uri.getQuery()))
            decode.encodedQuery(uri.getQuery());
        if (isValid(uri.getFragment()))
            decode.encodedFragment(uri.getFragment());
        if (isValid(uri.getPath()))
            decode.encodedPath(uri.getPath());
        decode.encodedAuthority(decodeAuthority(uri));
        return decode.build().toString();
    }

    public static String decodeUrlHost(String url) {
        String host = Uri.parse(url).getHost();
        if (host != null)
            return decodePunyCode(host);
        return null;
    }

    private static String decodePunyCode(String domain) {
        return IDN.toUnicode(domain);
    }

    private static String decodeAuthority(Uri uri) {
        String host = uri.getHost();
        if (TextUtils.isEmpty(host)) {
            return uri.getEncodedAuthority();
        } else {
            host = decodePunyCode(host);
        }

        String userInfo = uri.getUserInfo();
        boolean noUserInfo = TextUtils.isEmpty(userInfo);
        int port = uri.getPort();

        if (noUserInfo && port == -1)
            return host;

        StringBuilder builder = new StringBuilder();

        if (!noUserInfo) {
            if (isValid(userInfo)) {
                builder.append(userInfo).append("@");
            } else {
                builder.append(uri.getEncodedUserInfo()).append("@");
            }
        }

        builder.append(host);

        if (port > -1) {
            builder.append(":").append(port);
        }

        return builder.toString();
    }

    private static final char INVALID_CHAR = '\uFFFD';

    private static boolean isValid(String str) {
        return str != null && !(str.indexOf(INVALID_CHAR) > -1);
    }
}

@@ -903,32 +903,766 @@
 eUrl(Uri uri) %7B%0A
+        if (uri.isOpaque()) %7B%0A            StringBuilder builder = new StringBuilder(uri.getScheme()).append(%22:%22);%0A            if (isValid(uri.getSchemeSpecificPart())) %7B%0A                builder.append(uri.getSchemeSpecificPart());%0A            %7D else %7B%0A                builder.append(uri.getEncodedSchemeSpecificPart());%0A            %7D%0A            String fragment = uri.getFragment();%0A            if (!TextUtils.isEmpty(fragment)) %7B%0A                builder.append(%22#%22);%0A                if (isValid(fragment)) %7B%0A                    builder.append(fragment);%0A                %7D else %7B%0A                    builder.append(uri.getEncodedFragment());%0A                %7D%0A            %7D%0A            return builder.toString();%0A        %7D else %7B%0A    
         Uri.Buil
@@ -1691,32 +1691,36 @@
 Upon();%0A        
+    
 if (isValid(uri.
@@ -1736,32 +1736,36 @@
 )))%0A            
+  
+  
 decode.encodedQu
@@ -1781,24 +1781,28 @@
 etQuery());%0A
+    
         if (
@@ -1833,32 +1833,36 @@
 )))%0A            
+    
 decode.encodedFr
@@ -1888,32 +1888,36 @@
 ent());%0A        
+  
+  
 if (isValid(uri.
@@ -1924,24 +1924,28 @@
 getPath()))%0A
+    
             
@@ -1979,32 +1979,36 @@
 ath());%0A        
+    
 decode.encodedAu
@@ -2038,32 +2038,36 @@
 (uri));%0A        
+  
+  
 return decode.bu
@@ -2076,32 +2076,42 @@
 d().toString();%0A
+        %7D%0A
     %7D%0A%0A    publi

corresponds to opaque url