/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */

package net.ranides.assira.io.uri;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Optional;
import net.ranides.assira.collection.maps.MapCollectors;
import net.ranides.assira.collection.maps.MultiMap;
import net.ranides.assira.text.Charsets;
import net.ranides.assira.text.StringTraits;
import net.ranides.assira.text.StringUtils;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public final class URIUtils {
    
    private URIUtils() {
        /* utility class */
    }

    public static String decodeURL(String input) {
        return decodeURL(input, Charsets.UTF8);
    }
	
	public static String decodeURL(String input, Charset charset) {
        try {
            return URLDecoder.decode(input, charset.name());
        } catch(UnsupportedEncodingException cause) {
			throw new AssertionError("Unsupported charset: " + charset, cause);
        }
    }
    
    public static String encodeURL(String input) {
        return encodeURL(input, Charsets.UTF8);
    }
    
    public static String encodeURL(String input, Charset charset) {
        try {
            return URLEncoder.encode(input, charset.name());
        } catch(UnsupportedEncodingException cause) {
			throw new AssertionError("Unsupported charset: " + charset, cause);
        }
    }
    
    public static File getFile(URI uri) {
        String p = uri.getSchemeSpecificPart();
        String q = uri.getQuery();
        int qe = (null==q ? 0 : q.length()+1);
        
        // strip repeated "/"
        int n = p.length();
        int offset = 0;
        while( offset<n && '/'==p.charAt(offset) ) { 
			offset++; 
		}
        if(offset>0) {
            offset--;
        }
        
        return new File(p.substring(offset, p.length() - qe));
    }
    
    public static Optional<String> getLogin(URI uri) {
        String ui = uri.getUserInfo();
        return (null != ui) ? Optional.of(ui.split(":")[0]) : Optional.empty();
    }
    
    public static Optional<String> getPassword(URI uri) {
        String ui = uri.getUserInfo();
        return StringUtils.contains(ui, ':') ? Optional.of(StringUtils.after(ui, ":")) : Optional.empty();
    }
    
    public static Optional<Integer> getPort(URI uri) {
        int port = uri.getPort();
        return -1 != port ? Optional.of(port) : Optional.empty();
    }
    
    public static MultiMap<String,String> getParams(URI uri) {
        String query = uri.getQuery();
        if(StringTraits.isEmpty(query)) {
            return MultiMap.empty();
        }
        return Arrays
            .stream(query.split("&"))
            .map(v -> v.split("="))
            .collect(MapCollectors.multimap(p -> paramName(p), p -> paramValue(p)));
    }
    
    public static Optional<String> getParam(URI uri, String param) {
        String query = uri.getQuery();
        if(StringTraits.isEmpty(query)) {
            return Optional.empty();
        }
        return Arrays
            .stream(query.split("&"))
            .map(v -> v.split("="))
            .filter(p -> param.equals(paramName(p)))
            .map(p -> paramValue(p))
            .findFirst();
    }
    
    private static String paramName(String[] array) {
        return array.length > 0 ? array[0] : "";
    }
    
    private static String paramValue(String[] array) {
        return array.length > 1 ? array[1] : "";
    }
    
}
