/*
 * 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.
 */

//-----------------------------------------------------------------------------
// Session Controll
//-----------------------------------------------------------------------------
package net.pms.dlna;

import java.io.File;
import java.util.List;
import java.util.ArrayList;
import java.net.InetAddress;
import java.net.InetSocketAddress;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.jboss.netty.channel.ChannelHandlerContext;

import net.pms.configuration.RendererConfiguration;
import net.pms.configuration.PmsConfiguration;

import net.pms.PMS;
import net.pms.util.PMSUtil;

public class  rz_SessionInfo {
	private static final Logger logger = LoggerFactory.getLogger(rz_SessionInfo.class);
	
	//session info entry
	//TODO: should be isolated from direct accsess to data
	public InetSocketAddress sa;
	public InetAddress ia;
	public DLNAResource CurrentDLNA;	//currently plaing dlna
	public DLNAResource CurrentFolder;	//currently opned folder
	public String CurrentFolderID;		//ID of curFolder
	public int CurrentSeekMode;         //current_seekmode, =0:unknown,=1:ByteSeek,=2:TimeSeek
	public int id;
	public int cur_stopped;   // =1: currentDLNA play stopped 
	
	public RendererConfiguration renderer;
	public int resume_mode;
	public ChannelHandlerContext ctx;
	public int channel_stat;
	public rz_ScriptExecutor scex; 
	public boolean is_aav,is_iav;
	public boolean initScript;
	public boolean dispIconEnable=true;   	//display renderer icon on status screen 
	public boolean isMyHost=false;   		//this is myHost(mySever) 
	public String fname;   //device friendlyName
	public String ia_str;  //String ipAddr
	public long resMinTime1;
	public long resMinTime2;

	public long playTimeTotal;  //total play time
	public long playTime;  		//play time from play pos
	public int playPos0;   		//play pos that terminal thinks
	public int playPos1_base;   //play pos on real autoPlay list
	public int playPos1;   		//play pos on real autoPlay list
	public double seek_bias;   	//sum of seek miss-match , for player that ignore timeseek
	
	//--- Meta params
	public static int rz_SysMetaTransFormatWeb= -1;  //-1: means not setted, sysytem common
	public static String rz_SysMetaWebOpt;
	public static String rz_SysMetaAAVOpt;
	public static String rz_SysMetaIAVOpt;
	
	public rz_SessionInfo() {
	}

	public RendererConfiguration getRenderer() {
		return renderer;
	}
	public RootFolder getRoot() {
		if(renderer==null) return null;
		return renderer.rootFolder;
	}
	
	public boolean getDispIconEnable() {
		return dispIconEnable;
	}
	public void setIsMyHost(boolean b) {
		isMyHost=b;
	}
	
	public void setFname(String fname) {
		this.fname=fname;
	}

	public void setRenderer(RendererConfiguration r) {
		if(PMS.rz_debug>1) PMS.dbg("setRenderer: renderer="+r);
		if(r==null) {
			logger.warn("rz_SessionInfo.setRenderer: renderer is null");
			return;
		}
		boolean initf=false;
		if(renderer==null) {
			//if(mode==1) { //mode=1: create clone of renderer r, and use clone
			if(PMS.rz_is_root_per_session) { //separete root per sessions even if same renderer type
				// create another clone of renderer r, and use it
				// B/C Original PMS: One Type of Renderer has One(Same:common) RootFolder.
				// So, must create new Renderer Instance for discrete RootFolder per session, even if Same Type of Renderer
				try {
					renderer=(RendererConfiguration)r.clone();  
					renderer.rootFolder=null;
					renderer.sess=this;
				} catch (CloneNotSupportedException e1) {
					logger.error("rz_SessionInfo.setRenderer: renderer clone creation error: " + e1.getMessage());
				}
				if(PMS.rz_debug>1) PMS.dbg("setRenderer: rz_is_root_per_session=true, renderer="+renderer);
			}
			else { //use same root within sessions of same renderer type
				renderer=r;
				if(PMS.rz_debug>1) PMS.dbg("setRenderer: rz_is_root_per_session=false, renderer="+renderer);
			}
			
			//---- init data
			resume_mode=r.getRZ_resume_mode();	//client_side_mode
			resMinTime1=(long)(r.getRZ_resume_play_min_time1()*1000);
			resMinTime2=(long)(r.getRZ_resume_play_min_time2()*1000);
			is_aav=PMS.rz_is_audio_as_video;
			if(r.getRZ_AudioAsVideo()>=0) {
				//override by renderer specific
				is_aav=r.getRZ_AudioAsVideo()==0?false:true;
			}
			is_iav=PMS.rz_is_image_as_video;
			if(r.getRZ_ImageAsVideo()>=0) {
				//override by renderer specific
				is_iav=r.getRZ_ImageAsVideo()==0?false:true;
			}
			
			//---- init RendererScriptParser
			if(initScript && PMS.rz_is_rend_script_enabled && renderer!=null) {
				PMS.dbg("rz_SessionInfo.setRenderer: Init Interpreter, renderer="+r);
				//--- init scriptExecutor (for TranscodeOptionScripts)
				List<?> slist0=PMS.getConfiguration().getScriptList();
				//PMS.dbg("SessionInfo: slist0="+slist0);
				
				List<?> slist1=renderer.getScriptList();
				//PMS.dbg("SessionInfo: slist1="+slist1);
				
				List<Object> slist=new ArrayList<Object>();
				if(slist0!=null) slist.addAll(slist0);
				if(slist1!=null) slist.addAll(slist1);
				if((slist!=null && slist.size()>0)) {
					scex=new rz_ScriptExecutor(renderer,this);
					scex.loadRz_TransOptScript(slist);
					scex.init();
				}
			}
		}
	}
		
	//---- get session common script values
	long sess_script_value_updated;
	int g_auto_play=-1; //initial: not setted yet
	public int getSessAutoPlay() {
		int auto_play= -1;
		boolean scripts_exist=(PMS.rz_is_rend_script_enabled && scex!=null);
		if(scripts_exist) {
			long RendererScriptLastModified=scex.getRz_ScriptLastModified();
			
			//if(PMS.rz_debug>1) PMS.dbg("getSessAutoPlay: sess_script_value_updated="+sess_script_value_updated
			//	+", RendererScriptLastModified="+RendererScriptLastModified);
			
			if(sess_script_value_updated<RendererScriptLastModified) {
				//if(PMS.rz_debug>1) PMS.dbg("getSessAutoPlay: script updated, re-parse rz_SysMetaAAVOpt");
				sess_script_value_updated=RendererScriptLastModified;
				if(rz_SysMetaAAVOpt!=null && rz_SysMetaAAVOpt.length()>0) {	
					String [] sopts=rz_SysMetaAAVOpt.split(",");
					for(String s1 :sopts) {
						if(s1.startsWith("--")) {
							String[] sm=s1.split("[\\s]+");  //split by spaces
							if(sm.length>1 && sm[0].equals("--auto_play")) {
								auto_play=Integer.parseInt(sm[1]);  //override by scripts
								//if(PMS.rz_debug>1) PMS.dbg("getSessAutoPlay: found auto_play in rz_SysMetaAAVOpt="+auto_play);
								break;
							}
						}
					}
				}
			}
		}
		if(auto_play>=0) {  //forced updated
			g_auto_play=auto_play;
		}
		if(g_auto_play<0 && renderer!=null) { //not setted yet
			g_auto_play=renderer.getRZ_AAV_AutoPlay();
		}
		if(PMS.rz_debug>1) PMS.dbg("getSessAutoPlay: end, auto_play="+g_auto_play);
		return g_auto_play;
	}

		
	@Override
	public String toString() {
		String rend=", conf="+renderer+", fName="+(fname==null?"unknown":fname)
		+", itsMe="+(isMyHost==true?1:0)
			+", RootF="+(renderer==null?"null":renderer.rootFolder);
		
		return "[ ipAddr=" + sa + rend +", (Current: DLNA=" + CurrentDLNA + ", Folder=" + CurrentFolder 
		 + ", FolderID=" + CurrentFolderID + ") ]";
	}
}
