/*
 * PS3 Media Server, for streaming any medias to your PS3.
 * Copyright (C) 2008  A.Brochard
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; version 2
 * of the License only.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package net.pms.newgui;

import java.awt.Component;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Locale;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.JPopupMenu;
import javax.swing.JMenuItem;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;

import net.pms.Messages;
import net.pms.PMS;
import net.pms.configuration.PmsConfiguration;
import net.pms.configuration.Build;
import net.pms.external.ExternalFactory;
import net.pms.external.ExternalListener;
import net.pms.util.KeyedComboBoxModel;
import net.pms.util.PMSUtil;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.factories.Borders;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.sun.jna.Platform;

public class rz_WebTab {
	private static final Logger logger = LoggerFactory.getLogger(GeneralTab.class);
	
	//---- web transcode settings 
	private JComboBox<String> sel_cq;
	private JCheckBox cbtn_remux;
	private JCheckBox cbtn_resize;
	private JTextField dp_width;
	private JTextField dp_height;

	//---- web search 
	private JTextField sc_api;
	private JTextField sc_str;
	private JTextField sc_opt;
	int	sc_num;    //selected num in list

	//---- web channel 
	private JTextField ch_api;
	private JTextField ch_str;
	private JTextField ch_opt;
	int	ch_num;    //selected num in list
	
	//---- web streams 
	private JTextField strm1;
	private JTextField strm2;
	private JTextField strm3;
	
	private JPanel pPlugins;
	private final PmsConfiguration configuration;
	
	private String dt_sc_api;
	private String dt_sc_str;
	private String dt_sc_opt;
	private String dt_ch_api;
	private String dt_ch_str;
	private String dt_ch_opt;
	private String dt_strm1;
	private String dt_strm2;
	private String dt_strm3;
	private long dt_modified_time;
	private File qsConf;
	
	//public ArrayList<String> gglvsch_ptn_grp=new ArrayList<String>();
	//public ArrayList<String> gglvsch_ptn_url=new ArrayList<String>();
	public ArrayList<String> gglvsch_ptn_grp=new ArrayList<String>();
	public ArrayList<String> gglvsch_ptn_url=new ArrayList<String>();
	public String gglvsch_ptn_thumbid;
	public String gglvsch_ptn_thumbdt;
	
	public ArrayList<String[]> sc_defaults = new ArrayList<String[]>();
	public ArrayList<String[]> ch_defaults = new ArrayList<String[]>();
	public ArrayList<String[]> st_defaults = new ArrayList<String[]>();
	
	public ArrayList<String[]> sc_defaults_bk = new ArrayList<String[]>();
	public ArrayList<String[]> ch_defaults_bk = new ArrayList<String[]>();
	public ArrayList<String[]> st_defaults_bk = new ArrayList<String[]>();
	
	// moved to ClipList.conf
	//public ArrayList<String> pathlist_aav = new ArrayList<String>();	//audio clip_path_list
	//public ArrayList<String> pathlist_iav = new ArrayList<String>();	//visual clip_path_list
	
	private String[] quality_sel=  {"Best","High","Medium","Low"};	//for SelectionBox
	private String[] quality_para= {"best","high","medium","low"};	//for config_param value
	
	private String[][] sc_defaults1= {	//Search api defaults
		//{type}	 ,{path}        ,{name}			,{base_url},{search_string},{options}
		{"videofeed" ,"VideoSearch" ,"Youtube"    	,"https://www.google.co.jp/search?tbm=vid&q=","","&num=50&start={$pval=0;50}"},
		{"videofeed" ,"VideoSearch" ,"DailyMotion"	,"http://www.dailymotion.com/rss/relevance/search/","","/{$pval=1;2;3;4}"},
		{"videofeed" ,"VideoSearch" ,"Nicovideo"  	,"http://www.nicovideo.jp/tag/","","?sort=f&rss=2.0"},
		{"imagefeed" ,"ImageSearch" ,"Google Image" ,"https://www.google.co.jp/images?q=","","&num=50&start={$pval=0;50}"},
		{"imagefeed" ,"ImageSearch" ,"Picasa"  		,"http://picasaweb.google.com/data/feed/base/all?kind=photo&imgmax=1600&alt=rss&q=","","&max-results=200&start-index=1"},
		{"imagefeed" ,"ImageSearch" ,"Flickr"  		,"http://api.flickr.com/services/feeds/photos_public.gne?tags=","",""},
	};
	private String[][] ch_defaults1= {	//Channel api defaults
		//{type}	 ,{path}   ,{name}			,{base_url},{channel_id},{options}
		{"videofeed" ,"Channel","YT user"		,"http://gdata.youtube.com/feeds/api/users/","(user id)","/uploads?orderby=updated&start-index=1&max-results=50"},
		{"videofeed" ,"Channel","YT playlist"	,"http://gdata.youtube.com/feeds/api/playlists/","(playlist id)","?start-index=1&max-results=50"},
		{"videofeed" ,"Channel","DM user"		,"http://www.dailymotion.com/rss/user/","(user id)","/1"},
		{"videofeed" ,"Channel","DM playlist"	,"http://www.dailymotion.com/rss/playlists/user/","(user id)","/1"},
		{"videofeed" ,"Channel","DM mychannel"	,"http://www.dailymotion.com/rss/mychannel/","(channel id)","/1#"},
	};
	private String[][] st_defaults1= {	//Stream defaults
		//{type}	  ,{path}   ,{name}     ,{stream_url}
		{"videostream","Stream" ,"Stream1"	,"" },
		{"videostream","Stream" ,"Stream2"	,"" },
		{"videostream","Stream" ,"Stream3"	,"" },
		{"videostream","Stream" ,"Stream4"	,"" },
	};

	rz_WebTab(PmsConfiguration configuration) {
		this.configuration = configuration;
	}
	
	private void setGlobal() {
		PMS.rz_SetKwd(dt_sc_str);
		//PMS.dt_sc_str=dt_sc_str;
		PMS.dt_ch_str=dt_ch_str;
		PMS.dt_modified_time=dt_modified_time;
	}
	
	public void initGlobal() {  //should be revised
		PMS.rz_SetKwd("");
		//PMS.dt_sc_str="";
		PMS.dt_ch_str="";
		PMS.dt_modified_time=dt_modified_time;
	}

	public JComponent build() {
		int ypos,ypos_sv,xpos;
		int xpos_lb;	//1st, label
		int xpos_tf;	//2nd, textfield
		int xpos_bt;	//3rd, button
		int width_tf;	//width of textfield
		int width_tt;	//width of title line

		//---- Layout
		/*
		------------------------------------------------------------------------------------------
		com.jgoodies.forms.layout.FormLayout by JGoodies form layout implementation 
		The resize behavior is defined by a non-negative resize weight. 
		The syntax for the string representation for columns and rows is as follows: 
		------------------------------------------------------------------------------------------
		Spec 1: Column and Row String Encoding Syntax 
		------------------------------------------------------------------------------------------
		columnSpec            ::=   [columnAlignment:] size [:resizeBehavior] 
		rowSpec               ::=   [rowAlignment :] size [:resizeBehavior] 
		columnAlignment       ::=   LEFT | CENTER | RIGHT | FILL | L | C | R | F 
		rowAlignment          ::=   TOP | CENTER | BOTTOM | FILL | T | C | B | F 
		size                  ::=   constantSize | componentSize | boundedSize 
		componentSize         ::=   MIN | PREF | DEFAULT | M | P | D 
		constantSize          ::=   <integer>integerUnit | <double>doubleUnit 
		integerUnit           ::=   PX | PT | DLU 
		doubleUnit            ::=   IN | MM | CM 
		boundedSize           ::=   MIN(constantSize;componentSize)| MAX(constantSize;componentSize) 
		resizeBehavior        ::=   NONE | GROW | GROW(<double>) | G(<double>)
		------------------------------------------------------------------------------------------
		Spec 2: Cell Constraints String Encoding Syntax 
		------------------------------------------------------------------------------------------
		constraints 	::= column, row [, colSpan, rowSpan][, hAlign, vAlign] 
		column			::= <integer> 
		row 			::= <integer> 
		colSpan 		::= <integer> 
		rowSpan 		::= <integer> hAlign ::= LEFT | CENTER | RIGHT | DEFAULT | FILL | L | C | R | D | F 
		vAlign 			::= TOP | CENTER | BOTTOM | DEFAULT | FILL | T | C | B | D | F
		------------------------------------------------------------------------------------------
		<Notes>
		------------------------------------------------------------------------------------------
		pref,p 	is for 'preferred size'
		min 	is for  'minimum size', 
		dlu 	is a size unit that scales with the font.
		------------------------------------------------------------------------------------------
		*/

		FormLayout layout = new FormLayout(	
			// define mesh type layout
			//   1        2     3  4      5  6     7  8     9          10    11
			//"left:pref, 2dlu, p, 2dlu , p, 2dlu, p, 2dlu, pref:grow, 5dlu, p", 
			
			//---- 1st string: define_columns (size)
			//1      2     3  4     5  6     7  8     9  10    11 12    13 14    15 16    17 18      19    20
			"left:p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, p:grow, 5dlu, p", 
			//---- 2nd string: define_rows (size)
			"p,3dlu, p,3dlu, p,3dlu, p,3dlu, p,3dlu, p,3dlu, p,3dlu, p,3dlu, p,3dlu, p,3dlu, p,3dlu, p,3dlu, p,3dlu, p,3dlu, p,3dlu, p,3dlu, p,3dlu, p,3dlu, p,3dlu, p,3dlu, p");
		
		PanelBuilder builder = new PanelBuilder(layout);
		builder.setBorder(Borders.DLU4_BORDER);
		builder.setOpaque(true);

		CellConstraints cc = new CellConstraints();
		
		//---- set Initial_data(defaults) to PMS global
		initGlobal();

		xpos_lb=1;		//1st, label
		xpos_tf=3;		//2nd, textfield
		xpos_bt=20;		//3rd, button
		width_tf=16;	//width of textfield
		width_tt=20;	//width of title line
		
		//----------------------------------------------------------------------
		// Web Transcode settings
		//----------------------------------------------------------------------
		ypos=3;		//base y pos
		//---- separator
		JComponent sep_tr = builder.addSeparator("Web Transcode Settings", cc.xyw(1, ypos, width_tt));
		sep_tr = (JComponent) sep_tr.getComponent(0);
		sep_tr.setFont(sep_tr.getFont().deriveFont(Font.BOLD));
		
		//---- ContentsQuality (selection)
		ypos+=2;
		xpos=xpos_lb;
		builder.addLabel("ContentsQuality: ", cc.xy(xpos+0, ypos));
		sel_cq = new JComboBox<String>(quality_sel);
		ActionListener cbk_cq = new myListener_cq();
		sel_cq.addActionListener(cbk_cq);
		builder.add(sel_cq, cc.xy(xpos+=2, ypos));
		String level=configuration.getRZ_web_quality();
		boolean found=false;
		for(int i=0;i<quality_para.length;i++) {
			if(level.equals(quality_para[i])) {
				sel_cq.setSelectedIndex(i);
				found=true;
			}
		}
		if(!found) {
			logger.warn("Unknown quality_level=" + level);
			sel_cq.setSelectedIndex(0);
		}
		
		//---- RemuxWhenCompatible (checkbox)
		builder.addLabel(" ", cc.xy(xpos+=2, ypos));	//dummy space
		cbtn_remux=new JCheckBox("RemuxWhenCompatible    ");
	    ActionListener cbk_remux = new myListener_remux();
		cbtn_remux.addActionListener(cbk_remux);
		builder.add(cbtn_remux, cc.xy(xpos+=2, ypos));
		if(configuration.isRZ_web_remux()) cbtn_remux.setSelected(true);
		else cbtn_remux.setSelected(false);

		//---- ForceResize (checkbox)
		cbtn_resize=new JCheckBox("ForceResize");
	    ActionListener cbk_resize = new myListener_resize();
		cbtn_resize.addActionListener(cbk_resize);
		builder.add(cbtn_resize, cc.xy(xpos+=2, ypos));
		if(configuration.isRZ_web_force_resize()) cbtn_resize.setSelected(true);
		else cbtn_resize.setSelected(false);
		
		//---- Resize_w/h (textfield x2)
		builder.addLabel("    Width: ", cc.xy(xpos+=2, ypos));
		dp_width = new JTextField(6);
		builder.add(dp_width, cc.xyw(xpos+=2, ypos, 1));
		int w=configuration.getRZ_web_resize_w();
		dp_width.setText(""+w);
		dp_width.addActionListener(new ActionListener () {
			@Override
			public void actionPerformed(ActionEvent e) {
				int w=Integer.parseInt(dp_width.getText());
				configuration.setRZ_web_resize_w(w);
				//PMS.dbg("resize_w="+w);
			}		
		});

		builder.addLabel("    Height: ", cc.xy(xpos+=2, ypos));
		dp_height = new JTextField(6);
		builder.add(dp_height, cc.xyw(xpos+=2, ypos, 1));
		int h=configuration.getRZ_web_resize_h();
		dp_height.setText(""+h);
		dp_height.addActionListener(new ActionListener () {
			@Override
			public void actionPerformed(ActionEvent e) {
				int h=Integer.parseInt(dp_height.getText());
				configuration.setRZ_web_resize_h(h);
				//PMS.dbg("resize_h="+h);
			}		
		});
		
		//----------------------------------------------------------------------
		// Web Search filelds
		//----------------------------------------------------------------------
		//---- Title
		//ypos=3;
		ypos+=2;
	    JMenuItem item;
		
		JComponent sep_sc = builder.addSeparator("Web Quick Search ", cc.xyw(1, ypos, width_tt));
		sep_sc = (JComponent) sep_sc.getComponent(0);
		sep_sc.setFont(sep_sc.getFont().deriveFont(Font.BOLD));
		String[] dt_sc=sc_defaults.get(0);

		//---- Search Api's URL
		ypos+=2;
		ypos_sv=ypos;	//for later use
		sc_api = new JTextField(dt_sc[3]);
		builder.addLabel("Search Base  ", cc.xy(1, ypos));
		builder.add(sc_api, cc.xyw(xpos_tf, ypos, width_tf));
		
		//---- Search String
		ypos+=2;
		sc_str = new JTextField(dt_sc[4]);
		builder.addLabel("Search String  ", cc.xy(1, ypos));
		builder.add(sc_str, cc.xyw(xpos_tf, ypos, width_tf));
		
		//---- Search Options
		ypos+=2;
		sc_opt = new JTextField(dt_sc[5]);
		builder.addLabel("Search Options  ", cc.xy(1, ypos));
		builder.add(sc_opt, cc.xyw(xpos_tf, ypos, width_tf));

		//----------------------------------------------------------------------
		// Web Search selections
		//----------------------------------------------------------------------
		//---- Selection popup 
		final JPopupMenu popup_sc = new JPopupMenu();
	    //PMS.dbg("sc_defaults.size="+sc_defaults.size());
	    ActionListener cbk_sc = new myListener_sc();

	    for(int i=0;i<sc_defaults.size();i++) {
			item=new JMenuItem(sc_defaults.get(i)[2]);
	   	    popup_sc.add(item);
			item.addActionListener(cbk_sc);
			item.setActionCommand(""+i);
		}

		//---- Slection Button (Select Sites)
		final JButton btn_sc = new JButton("Select");
		btn_sc.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				popup_sc.show(btn_sc,10,10);
			}
		});
		builder.add(btn_sc, cc.xy(xpos_bt, ypos_sv));

		//----------------------------------------------------------------------
		// Web Quick Channel fields
		//----------------------------------------------------------------------
		//---- Title
		ypos+=4;	
		JComponent sep_ch = builder.addSeparator("Web Quick Channel ", cc.xyw(1, ypos, width_tt));
		sep_ch = (JComponent) sep_ch.getComponent(0);
		sep_ch.setFont(sep_ch.getFont().deriveFont(Font.BOLD));
		String[] dt_ch=ch_defaults.get(0);

		//---- Feed Api's URL
		ypos+=2;
		ypos_sv=ypos;
		ch_api = new JTextField(dt_ch[3]);
		builder.addLabel("Channel Base ", cc.xy(1, ypos));
		builder.add(ch_api, cc.xyw(xpos_tf, ypos, width_tf));

		//---- Channel String(user id)
		ypos+=2;
		ch_str = new JTextField(dt_ch[4]);
		builder.addLabel("Channel ID  ", cc.xy(1, ypos));
		builder.add(ch_str, cc.xyw(xpos_tf, ypos, width_tf));
		
		//---- Channel Options
		ypos+=2;
		ch_opt = new JTextField(dt_ch[5]);
		builder.addLabel("Channel Options  ", cc.xy(1, ypos));
		builder.add(ch_opt, cc.xyw(xpos_tf, ypos, width_tf));
		
		//----------------------------------------------------------------------
		// Web Quick Channel selections
		//----------------------------------------------------------------------
		//---- Selection popup 
		final JPopupMenu popup_ch = new JPopupMenu();
	    ActionListener cbk_ch = new myListener_ch();
	    //PMS.dbg("ch_defaults.size="+ch_defaults.size());

		for(int i=0;i<ch_defaults.size();i++) {
	    	item=new JMenuItem(ch_defaults.get(i)[2]);
	   	    popup_ch.add(item);
			item.addActionListener(cbk_ch);
			item.setActionCommand(""+i);
		}
		
		//---- Slection Button (Set Defaults)
		final JButton btn_ch = new JButton("Select");
		btn_ch.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				popup_ch.show(btn_ch,10,10);
			}
		});
		builder.add(btn_ch, cc.xy(xpos_bt, ypos_sv));

		//----------------------------------------------------------------------
		// Web Quick Stream 
		//----------------------------------------------------------------------
		//---- title
		ypos+=4;
		JComponent sep_st = builder.addSeparator("Web Quick Stream", cc.xyw(1, ypos, width_tt));
		sep_st = (JComponent) sep_st.getComponent(0);
		sep_st.setFont(sep_st.getFont().deriveFont(Font.BOLD));

		//---- Stream 1
		ypos+=2;	//should be odd num
		strm1 = new JTextField(st_defaults.get(0)[3]);
		builder.addLabel("Stream 1  ", cc.xy(1, ypos));
		builder.add(strm1, cc.xyw(xpos_tf, ypos, width_tf));

		//---- Stream 2
		ypos+=2;
		strm2 = new JTextField(st_defaults.get(1)[3]);
		builder.addLabel("Stream 2  ", cc.xy(1, ypos));
		builder.add(strm2, cc.xyw(xpos_tf, ypos, width_tf));
		
		//---- Stream 3
		ypos+=2;
		strm3 = new JTextField(st_defaults.get(2)[3]);
		builder.addLabel("Stream 3  ", cc.xy(1, ypos));
		builder.add(strm3, cc.xyw(xpos_tf, ypos, width_tf));
		
		//----------------------------------------------------------------------
		// Control Buttons
		//----------------------------------------------------------------------
		ypos+=4;
		JComponent sep_bt = builder.addSeparator("Web Contents Update", cc.xyw(1, ypos, 9));
		sep_bt = (JComponent) sep_bt.getComponent(0);
		sep_bt.setFont(sep_bt.getFont().deriveFont(Font.BOLD));

		ypos+=2;
		//---- Update Button 1 (Set Quick Actions)
		JButton btn1 = new JButton("Update Quick Data");
		btn1.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				sc_defaults.get(sc_num)[3]=sc_api.getText();
				sc_defaults.get(sc_num)[4]=sc_str.getText();
				sc_defaults.get(sc_num)[5]=sc_opt.getText();
				ch_defaults.get(ch_num)[3]=ch_api.getText();
				ch_defaults.get(ch_num)[4]=ch_str.getText();
				ch_defaults.get(ch_num)[5]=ch_opt.getText();
				//dt_strm1=strm1.getText();
				//dt_strm2=strm2.getText();
				//dt_strm3=strm3.getText();
				st_defaults.get(0)[3]=strm1.getText();
				st_defaults.get(1)[3]=strm2.getText();
				st_defaults.get(2)[3]=strm3.getText();
				
				dt_sc_str=sc_str.getText();
				dt_ch_str=ch_str.getText();
				dt_modified_time=System.currentTimeMillis();
				setGlobal();	// set inputted data to PMS global
			}
		});
		builder.add(btn1, cc.xy(1, ypos));
		
		//---- Button 2 (Reset Quick Actions)
		//builder.addLabel(" ", cc.xy(2, ypos));	//dummy for space
		JButton btn2 = new JButton("Reset All");
		btn2.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				//value copy from backup
				strArrayCopyByValue(sc_defaults_bk,sc_defaults);
				strArrayCopyByValue(ch_defaults_bk,ch_defaults);
				strArrayCopyByValue(st_defaults_bk,st_defaults);
				
				// following are not copy value, but copy address 
				// so, change target will also change according backups
				/*
				sc_defaults=new ArrayList<String[]>(sc_defaults_bk);
				ch_defaults=new ArrayList<String[]>(ch_defaults_bk);
				st_defaults=new ArrayList<String[]>(st_defaults_bk);
				*/

				String[] dt_sc=sc_defaults.get(sc_num);
				String[] dt_ch=ch_defaults.get(ch_num);
				String[] dt_st;
				sc_api.setText(dt_sc[3]);
				sc_str.setText(dt_sc[4]);
				sc_opt.setText(dt_sc[5]);
				ch_api.setText(dt_ch[3]);
				ch_str.setText(dt_ch[4]);
				ch_opt.setText(dt_ch[5]);
				if(st_defaults.size()>0) {
					strm1.setText(st_defaults.get(0)[3]);
				}
				if(st_defaults.size()>1) {
					strm2.setText(st_defaults.get(1)[3]);
				}
				if(st_defaults.size()>2) {
					strm3.setText(st_defaults.get(2)[3]);
				}
			}
		});
		builder.add(btn2, cc.xyw(3, ypos,3));

		//---- Button 3 (Update Web Contents)
		//builder.addLabel(" ", cc.xy(4, ypos));	//dummy for space
		JButton btn3 = new JButton("Update Other WebContens");
		btn3.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				PMS.dt_web_update_time=System.currentTimeMillis();
			}
		});
		builder.add(btn3, cc.xy(7, ypos));
		
		//----------------------------------------------------------------------
		// Main panel
		//----------------------------------------------------------------------
		JPanel panel = builder.getPanel();
		JScrollPane scrollPane = new JScrollPane(
			panel,
			JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
			JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		return scrollPane;
	}
	
	private void msgbox(String msg) {
		JOptionPane.showMessageDialog(
			(JFrame) (SwingUtilities.getWindowAncestor((Component) PMS.get().getFrame())),
			msg,"Information",
			JOptionPane.INFORMATION_MESSAGE);
	}
	
	class myListener_sc implements ActionListener{
	    public void actionPerformed(ActionEvent e) {
	    	JMenuItem mi = (JMenuItem)e.getSource();
	    	//PMS.dbg("selected sc getText="+mi.getText()+", getActionCommand="+mi.getActionCommand());
		    //PMS.dbg("sc_defaults.size="+sc_defaults.size());
		    int i=Integer.parseInt(mi.getActionCommand());
	        sc_api.setText(sc_defaults.get(i)[3]);
			sc_str.setText(sc_defaults.get(i)[4]);
			sc_opt.setText(sc_defaults.get(i)[5]);
	    	sc_num=i;
		}
	}

	class myListener_ch implements ActionListener{
	    public void actionPerformed(ActionEvent e) {
	    	JMenuItem mi = (JMenuItem)e.getSource();
	    	//PMS.dbg("selected ch getText="+mi.getText()+", getActionCommand="+mi.getActionCommand());
		    //PMS.dbg("ch_defaults.length="+ch_defaults.length);
		    int i=Integer.parseInt(mi.getActionCommand());
			ch_api.setText(ch_defaults.get(i)[3]);
			ch_str.setText(ch_defaults.get(i)[4]);
			ch_opt.setText(ch_defaults.get(i)[5]);
	    	ch_num=i;
		}
	}
	
	class myListener_cq implements ActionListener{	//ContentsQuality selection
	    public void actionPerformed(ActionEvent e) {
	    	int sel = sel_cq.getSelectedIndex();
	    	//PMS.dbg("selected index="+sel);
	    	configuration.setRZ_web_quality(quality_para[sel]);
		}
	}
	class myListener_remux implements ActionListener{	//RemuxWhenCompatible checkbtn
	    public void actionPerformed(ActionEvent e) {
	    	boolean sel = cbtn_remux.isSelected();
	    	PMS.dbg("RemuxWhenCompatible ="+sel);
	    	if(sel) configuration.setRZ_web_remux(true);
	    	else configuration.setRZ_web_remux(false);
		}
	}
	class myListener_resize implements ActionListener{	//ForceResize checkbtn
	    public void actionPerformed(ActionEvent e) {
	    	boolean sel = cbtn_resize.isSelected();
	    	PMS.dbg("ForceResize ="+sel);
	    	if(sel) configuration.setRZ_web_force_resize(true);
	    	else configuration.setRZ_web_force_resize(false);
		}
	}
	
	public void loadConf(File qsConf) {
		PMS.dbg("loadConf: start , file="+qsConf.getName());
		//File qsConf = new File(configuration.getProfileDirectory(), "WEB_QS.conf");
		
		this.qsConf=qsConf;
		sc_defaults.clear();
		ch_defaults.clear();
		if (!qsConf.exists()) {
			// load from inner init_table
			for(int i=0;i<sc_defaults1.length;i++) {
				sc_defaults.add(sc_defaults1[i]);
			}
			for(int i=0;i<ch_defaults1.length;i++) {
				ch_defaults.add(ch_defaults1[i]);
			}
			for(int i=0;i<st_defaults1.length;i++) {
				st_defaults.add(st_defaults1[i]);
			}
			return;
		}
		try {
			LineNumberReader br = new LineNumberReader(new InputStreamReader(new FileInputStream(qsConf), "UTF-8"));
			String line = null;
			String str;
			while ((line = br.readLine()) != null) {
				line = line.trim();
				PMS.dbg("loadConf: read line="+line);
				if(line.startsWith("#") || line.length()<=0) continue;
				if(line.startsWith("Qsearch=")) {
					str=line.substring("Qsearch=".length()).trim();
					String[] values=PMSUtil.splitx1(str,",");  //split by separator without escaped
					if(values.length>=4) {
						//for(String s: values) s=s.trim();
						sc_defaults.add(values);
					}
					else {
						PMS.dbg("Illegal params count <4: line="+line);
					}
				}
				else if(line.startsWith("Qchannel=")) {
					str=line.substring("Qchannel=".length()).trim();
					String[] values=PMSUtil.splitx1(str,",");  //split by separator without escaped
					if(values.length>=4) {
						//for(String s: values) s=s.trim();
						ch_defaults.add(values);
					}
					else {
						PMS.dbg("Illegal params count <4: line="+line);
					}
				}
				else if(line.startsWith("Qstream=")) {
					str=line.substring("Qstream=".length()).trim();
					String[] values=PMSUtil.splitx1(str,",");  //split by separator without escaped
					if(values.length>=2) {
						//for(String s: values) s=s.trim();
						st_defaults.add(values);
					}
					else {
						PMS.dbg("Illegal params count <2: line="+line);
					}
				}
				else if(line.startsWith("gglvsch_ptn_grp=")) {
					str=line.substring("gglvsch_ptn_grp=".length()).trim();
					gglvsch_ptn_grp.add(str);
				}
				else if(line.startsWith("gglvsch_ptn_url=")) {
					str=line.substring("gglvsch_ptn_url=".length()).trim();
					gglvsch_ptn_url.add(str);
				}
				else if(line.startsWith("gglvsch_ptn_thumbid=")) {
					str=line.substring("gglvsch_ptn_thumbid=".length()).trim();
					gglvsch_ptn_thumbid=str;
				}
				else if(line.startsWith("gglvsch_ptn_thumbdt=")) {
					str=line.substring("gglvsch_ptn_thumbdt=".length()).trim();
					gglvsch_ptn_thumbdt=str;
				}
				
				// moved to ClipList.conf
				/*
				else if(line.startsWith("cpath_aav=")) {
					str=line.substring("cpath_aav=".length()).trim();
					if(str.startsWith("\"") && str.endsWith("\"") && str.length()>2) {
						str=str.substring(1,str.length()-1);
					}
					if(str.length()<=0) continue;
					pathlist_aav.add(str);
				}
				else if(line.startsWith("cpath_iav=")) {
					str=line.substring("cpath_iav=".length()).trim();
					if(str.startsWith("\"") && str.endsWith("\"") && str.length()>2) {
						str=str.substring(1,str.length()-1);
					}
					if(str.length()<=0) continue;
					pathlist_iav.add(str);
				}
				*/
			}
			br.close();
		} catch (Exception e) {
			e.printStackTrace();
			logger.warn("Unexpected error in WEB_QS.conf: " + e.getMessage());
		}
		
		if(st_defaults.size()<3) {
			for(int i=st_defaults.size();i<3;i++) {
				st_defaults.add(st_defaults1[i]);
			}
		}
		//---- backup for reset
		strArrayCopyByValue(sc_defaults,sc_defaults_bk);
		strArrayCopyByValue(ch_defaults,ch_defaults_bk);
		strArrayCopyByValue(st_defaults,st_defaults_bk);
		
		if(gglvsch_ptn_grp.size()==0 && gglvsch_ptn_url.size()==0) {
			gglvsch_ptn_grp.add("div[class=g");
			gglvsch_ptn_grp.add("a[href*=http://");
		}
		
		if(PMS.rz_debug>0) {
			PMS.dbg("====================================");
			for(int i=0;i<sc_defaults.size();i++) {
				String[] values=sc_defaults.get(i);
				for(int j=0;j<values.length;j++) {
					PMS.dbg("rz_WebTab.loadConf: i="+i+", j="+j+", value="+values[j]);
				}
			}
		}
	}
	
	private void strArrayCopyByValue(ArrayList<String[]>src, ArrayList<String[]>dest) {
		dest.clear();
		for(String[] mp : src) {
			String[] mpw=new String[mp.length];
			for(int i=0;i<mp.length;i++) {
				mpw[i]=new String(mp[i]);
			}
			//System.arraycopy(mp,0,mpw,0,mp.length); //arraycopy can't copy String value
			//mpw=mp.clone();	//clone() can't copy String value
			dest.add(mpw);
		}
	}
}

