/*
 * Copyright (c) 2014-2021 by Wen Yu
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the Eclipse
 * Public License, v. 2.0 are satisfied: GNU General Public License, version 2
 * or any later version.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
 */

package pixy.util;

import java.security.ProtectionDomain;
import java.security.CodeSource;
import java.util.Arrays;
import java.util.regex.Pattern;
import java.io.PrintStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.URI;
import java.net.URL;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * A common language utility class
 * 
 * @author Wen Yu, yuwen_66@yahoo.com
 * @version 1.0 09/19/2012
 */
public class LangUtils {
	// Obtain a logger instance
	private static final Logger LOGGER = LoggerFactory.getLogger(LangUtils.class);
	
	private LangUtils(){} // Prevents instantiation
	
	// TODO: need to rewrite this method (may have to create and return a new class Rational)
	public static long[] doubleToRational(double number) {
		// Code below doesn't work for 0 and NaN - just check before
		if((number == 0.0d) || Double.isNaN(number)) {
			throw new IllegalArgumentException(number + " cannot be represented as a rational number");
		}
		
		long bits = Double.doubleToLongBits(number);

		long sign = bits >>> 63;
		long exponent = ((bits >>> 52) ^ (sign << 11)) - 1023;
		long fraction = bits << 12; // bits are "reversed" but that's not a problem

		long a = 1L;
		long b = 1L;

		for (int i = 63; i >= 12; i--) {
		    a = a * 2 + ((fraction >>> i) & 1);
		    b *= 2;
		}

		if (exponent > 0)
		    a *= 1 << exponent;
		else
		    b *= 1 << -exponent;

		if (sign == 1)
		    a *= -1;

		return new long[]{a, b};
	}
	
	// From Effective Java 2nd Edition. 
	// Use of asSubclass to safely cast to a bounded type token
	public static Annotation getAnnotation(AnnotatedElement element, String annotationTypeName) {
	     Class<?> annotationType = null; // Unbounded type token
	
	     try {
	            annotationType = Class.forName(annotationTypeName);
	     } catch (Exception ex) {
	            throw new IllegalArgumentException(ex);
	     }
	
	     return element.getAnnotation(annotationType.asSubclass(Annotation.class));
	}
	
	// Creates a friendly string representation of the class
	public static String getClassName(Class<?> c) {
	    String name = c.getName().replace('$','.');
	    
	    if (c.isArray()) {
	    	switch (name.charAt(1)) {
			    case 'B':
					name = "byte";
					break;
				case 'C':
					name = "char";
					break;
				case 'D':
					name = "double";
					break;
			    case 'F':
					name = "float";
					break;
			    case 'I':
					name = "int";
					break;
			    case 'J':
					name = "long";
					break;
			    case 'L':
					name = name.substring(2, name.length() - 1);
					break;
			    case 'S':
					name = "short";
					break;
			    case 'Z':
					name = "boolean";
					break;
	    	}
			name = name + "[]";
	    }
	    
	    return name;
	}
	
	/**
	 * @param m Method we want to probe generic type arguments.
	 * @param i the i'th parameter of the method.
	 * @return an array of parameterized Types for the i'th argument or an empty array. 
	 */
	public static Type[] getGenericTypeArguments(Method m, int i) {		 
		 try {
			 Type t = m.getGenericParameterTypes()[i];
		 
			 if(t instanceof ParameterizedType) {
				 ParameterizedType pt = (ParameterizedType) t;
				 return pt.getActualTypeArguments();
			 }
		 } catch(Exception e) {
			 LOGGER.error("Error probing generic type arguments!", e);
		 }
		 
		 return new Type[]{};
	}
	
	public static void log(String message, PrintStream out) {
		StackTraceElement se = Thread.currentThread().getStackTrace()[2];
		out.println("; " + message + " - [" + se.getClassName() + "." + se.getMethodName() +"(): line " + se.getLineNumber() + "]");		
	}
	
	/** Java language specific classes return null cSource */
	public static URL getLoadedClassLocation(Class<?> cls) {
		ProtectionDomain pDomain = cls.getProtectionDomain();
		CodeSource cSource = pDomain.getCodeSource();
		URL loc = (cSource==null)?null:cSource.getLocation(); 
		
		return loc; 
	}
	
	/**
	 * @param className A fully qualified class name with package information
	 * @return The location where the class has been loaded by the Java Virtual
	 * Machine or null.
	 */
	public static URL getLoadedClassLocation(String className) {
		Class<?> cls = null;
		
		try	{
			cls = Class.forName(className);
		} catch (ClassNotFoundException ex)	{
			return null;			
		}
		
		return getLoadedClassLocation(cls);
	}
	
	public static URL getLoadedClassURL(String className) {
		Class<?> cls = null;
		
		try	{
			cls = Class.forName(className);
		} catch (ClassNotFoundException ex) { 
			return null;			
		}
		
		ClassLoader classLoader = cls.getClassLoader();

		URL url = classLoader.getResource(className.replaceAll(Pattern.quote("."), "/") + ".class");
		
		return url;
	}
	
	// A convenience way to call main of other classes.
	// Based on something I am not sure where I got it.
	public static void invokeMain(String... args) {
		try {
		    Class<?> c = Class.forName(args[0]);
			Class<String[]> argTypes = String[].class;
			Method main = c.getDeclaredMethod("main", argTypes);
	  	    Object mainArgs = Arrays.copyOfRange(args, 1, args.length);
		    LOGGER.info("invoking {}.main()\n", c.getName());
		    main.invoke(null, mainArgs);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
	
	/**
	 * Converts long value to int hash code.
	 * 
	 * @param value long value
	 * @return int hash code for the long
	 */
	public static int longToIntHashCode(long value) {
		return Long.valueOf(value).hashCode();
	}
		
	// From stackoverflow.com
	public static URI relativize(URI base, URI child) {
		 // Normalize paths to remove . and .. segments
		 base = base.normalize();
		 child = child.normalize();

		 // Split paths into segments
		 String[] bParts = base.getPath().split("/");
		 String[] cParts = child.getPath().split("/");

		 // Discard trailing segment of base path
		 if (bParts.length > 0 && !base.getPath().endsWith("/")) {
		     System.arraycopy(bParts, 0, bParts, 0, bParts.length - 1);
			 // JDK1.6+ 
			 //bParts = java.util.Arrays.copyOf(bParts, bParts.length - 1);
		 }

		 // Remove common prefix segments
		 int i = 0;
		  
		 while (i < bParts.length && i < cParts.length && bParts[i].equals(cParts[i])) {
			i++;
		 }

		 // Construct the relative path
		 StringBuilder sb = new StringBuilder();
		  
		 for (int j = 0; j < (bParts.length - i); j++) {
			sb.append("../");
		 }
		  
		 for (int j = i; j < cParts.length; j++) {
			if (j != i) {
			  sb.append("/");
			}
			sb.append(cParts[j]);
		 }
		  
		 return URI.create(sb.toString());
	}	
}
