package net.pms.util;

import java.awt.AWTException;
import java.awt.Desktop;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.URI;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

import java.util.StringTokenizer;//regzamod
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import java.text.SimpleDateFormat;//regzamod

import net.pms.Messages;
import net.pms.PMS;
import net.pms.io.OutputParams;
import net.pms.newgui.LooksFrame;
import net.pms.dlna.DLNAResource;
import net.pms.dlna.DLNAMediaInfo;
import net.pms.dlna.DLNAMediaAudio;
import net.pms.dlna.DLNAMediaSubtitle;
import net.pms.dlna.virtual.VirtualFolder;
import net.pms.configuration.PmsConfiguration;

import org.slf4j.Logger;			// regzamod
import org.slf4j.LoggerFactory;		// regzamod

public class PMSUtil {
	private static final Logger logger = LoggerFactory.getLogger(PMSUtil.class);	//regzamod
	
	public static <T> T[] copyOf(T[] original, int newLength) {
		return Arrays.copyOf(original, newLength);
	}

	public static boolean isNetworkInterfaceLoopback(NetworkInterface ni) throws SocketException {
		return ni.isLoopback();
	}

	public static void browseURI(String uri) {
		try {
			Desktop.getDesktop().browse(new URI(uri));
		} catch (Exception e1) {
		}
	}

	public static void addSystemTray(final LooksFrame frame,String icname) {
		if (SystemTray.isSupported()) {
			SystemTray tray = SystemTray.getSystemTray();

			Image image = Toolkit.getDefaultToolkit().getImage(frame.getClass().getResource("/resources/images/icon-16.png"));

			PopupMenu popup = new PopupMenu();
			MenuItem defaultItem = new MenuItem(Messages.getString("LooksFrame.5"));
			MenuItem traceItem = new MenuItem(Messages.getString("LooksFrame.6"));

			defaultItem.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					frame.quit();
				}
			});

			traceItem.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					frame.setVisible(true);
				}
			});

			popup.add(traceItem);
			popup.add(defaultItem);

			//final TrayIcon trayIcon = new TrayIcon(image, "PS3 Media Server " + PMS.getVersion(), popup);
			final TrayIcon trayIcon = new TrayIcon(image, icname, popup);

			trayIcon.setImageAutoSize(true);
			trayIcon.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					frame.setVisible(true);
					frame.setFocusable(true);
				}
			});
			try {
				tray.add(trayIcon);
			} catch (AWTException e) {
				e.printStackTrace();
			}
		}
	}

	public static byte[] getHardwareAddress(NetworkInterface ni) throws SocketException {
		return ni.getHardwareAddress();
	}
		
	//---- regzamod add
	public static void strace() {
		StackTraceElement[] e = new Exception().getStackTrace();
		for (StackTraceElement element : e) {
			//System.out.println(element.getClassName() + "," + element.getMethodName());
			logger.info(element.getClassName() + "," + element.getMethodName());
		}
	}
	
	public static String[] rz_getFnameParams(String fileName) {
		//---- play start/end pos designated in filename_params
		String[] params= {null,null,null};	// start/stop time

		int sttp=fileName.indexOf("(@");
		if(sttp>-1) {
			String part=fileName.substring(sttp+2);
			int endp=part.indexOf(")");
			if(endp>-1) {	// param string found
				StringTokenizer st = new StringTokenizer(part.substring(0,endp), ",");
				while (st.hasMoreTokens()) {
					String token = st.nextToken().trim();
					if(token.startsWith("sd=")) {	//sound delay (msecs)
						params[0]=token.substring(3);
					}
					if(token.startsWith("sp=")) {	//play start pos (secs)
						params[1]=token.substring(3);
					}
					if(token.startsWith("ep=")) { //play end pos (secs)
						params[2]=token.substring(3);
					}
				}
			}	
		}
		//PMS.dbg("rz_getFnameParams: params="+params[0]+","+params[1]+","+params[2]+", fileName="+fileName);
		return params;
	}
	
	private static final int[] MULTIPLIER = new int[] { 1, 60, 3600, 24*3600}; 
	public static double convertTime(String time) {
		try {
			return Double.parseDouble(time);
		} catch (NumberFormatException e) {
			String[] arrs = time.split(":");
			double value, sum = 0;
			for (int i = 0; i < arrs.length; i++) {
				value = Double.parseDouble(arrs[arrs.length - i - 1]);
				sum += value * MULTIPLIER[i];
			}
			return sum;
		}

	}
	
	//private static SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss.mmm", Locale.US);
	private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd(EEE) HH:mm:ss.mmm", Locale.getDefault());
	public static String convTime2Date(long time) {
		//sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
		return sdf.format(new Date(time));
	}

	// Split by sep with handling escape:
	// "\+sep" ignoreed for sep, and converted to literal "sep" 
	public static String[] splitx1 (String str, String sep) {
		char[] charArray= Character.toChars(1);
		String ucode=new String(charArray);
		String str1=str.replaceAll("\\\\"+sep,ucode);
		String m[]=str1.split(sep,-1);
		for (int i=0; i<m.length; i++) {
			m[i]=m[i].replaceAll(ucode,sep);
		}
		return m;
	}
	
	//Sprit string by separater, with ignoring sep within double-quotations.
	//Sample  input string:  'p1="aaaa,= bbbb", p2=1 ,p3=on'
	//        output      :  {"p1","aaaa,=bbbb","p2","1","p3",on"}
	public static String[] splitx (String str, String[] sep) {
		Pattern p = Pattern.compile("\"(.*?)\""); //引用符内を得る正規表現
		Matcher m = p.matcher(str); //一致箇所の検索
		m.reset(); //検索開始点を先頭にする
		String r = ""; //変換後の文字列
		int z = 0; //最初の位置
		char[] charArray;
		String ucode[]=new String[sep.length];
		while( m.find() ) {
			int x = m.groupCount();
			for ( int i = 0 ; i < x ; i++ ) {
				String w = m.group(i); //引用符内の文字列
				r += str.substring(z, m.start(i)); //直前までを合成
				for(int j=0;j<sep.length;j++) {
					//code[j]=String.format("\\u%04X",j);
					charArray = Character.toChars(j);
					ucode[j] = new String(charArray);
					System.out.println("Separater unicode="+ucode[j]);
					w = w.replaceAll(sep[j],ucode[j]); //=を変換
				}
				r += w; //検索部分を繋げる
				z = m.end(i); //直後の位置を記録
			}
			r+=str.substring(z);
		}
		String[] a;
		if(true) {
			String regx=null;
			for(int j=0;j<sep.length;j++) {
				if(j==0) regx="("+sep[j]+")+";
				else  regx+="|("+sep[j]+")+";
			}
			a = r.split(regx); 
		}
		else {
			a = r.split(",+|=+"); //=,カンマで区切る
		}
		for ( int i = 0 ; i < a.length ; i++ ) {
			for(int j=0;j<sep.length;j++) {
				a[i] = a[i].replaceAll(ucode[j], sep[j]); //カンマに戻す
			}
			a[i]=a[i].trim();
			a[i] = a[i].replaceAll("^\"|\"$", ""); //先頭と末尾の"を除去
			a[i] = a[i].replaceAll("\"\"", "\"").trim(); //二重引用符の処理
				
		}
		return a;
	}
	
	//Search Vritual sub-folders under pa, according to the path (d1/d2/d3/../dn)
	//if not exists, create it 
	public static DLNAResource createDLNApath(DLNAResource pa, String path, String sep_i) {
		if(PMS.rz_debug>2) PMS.dbg("createDLNApath: path="+path+", sep="+sep_i);
		
		DLNAResource parent = null;
		String sep=null;
		if(sep_i!=null) sep=sep_i;
		else sep="(?!\\)/"; //bad
		String nodes[]=path.split(sep);
		//String nodes[]=path.split("\\"+File.separator);
		DLNAResource currentRoot = pa;
		for (String folder : nodes) {
			if(folder.length()<=0) continue;
			parent = currentRoot.searchByName0(folder);
			if (parent == null) {
				//PMS.dbg("createDLNApath: create folder="+folder);
				parent = new VirtualFolder(folder, "");
				currentRoot.addChild(parent);
			}
			currentRoot = parent;
		}
		return parent;
	}
	
	public static DLNAResource searchDLNApath(DLNAResource pa, String path, String sep_i) {
		DLNAResource ch = null;
		String sep=null;
		if(sep_i!=null) sep=sep_i;
		else sep="(?!\\)/"; //bad
		String nodes[]=path.split(sep);
		//String nodes[]=path.split("\\"+File.separator);
		DLNAResource currentRoot = pa;
		for (String folder : nodes) {
			if(folder.length()<=0) continue;
			ch = currentRoot.searchByName0(folder);
			if (ch == null) {
				return null;
			}
			currentRoot = ch;
		}
		return ch;
	}

	public static DLNAResource getDirectChild(DLNAResource top, DLNAResource obj) {
		DLNAResource pa,ch;
		ch=obj;
		pa=ch.getParent();
		while(pa!=null) {
			if(pa==top) {
				return ch;
			}
			ch=pa;
			pa=ch.getParent();
		}
		return null;
	}

	//---- regzamod add end
}
