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

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import net.pms.PMS;
import net.pms.configuration.PmsConfiguration;
import net.pms.dlna.DLNAResource;
import net.pms.dlna.virtual.VirtualVideoAction;
import net.pms.formats.MPG;
import net.pms.network.HTTPResource;
import net.pms.configuration.RendererConfiguration;

/**
 * Implements a container that when browsed, an action will be performed.
 * The class assumes that the action to be performed is to toggle a boolean value.
 * Because of this, the thumbnail is either a green tick mark or a red cross. Equivalent
 * videos are shown after the value is toggled.<p> 
 * However this is just cosmetic. Any action can be performed.
 */
 
//------------------------------------------------
// Change type of Buttons from File to Folder:
// that protects miss(unwanted)-selection of the Buttons by moving cursols
// B/C Folder type buttons only activated by Open the folder intendedly
// and not opened by moving cursols
//------------------------------------------------
//public abstract class rz_VirtualVideoActionF extends VirtualFolder {
public class rz_VirtualVideoActionF extends DLNAResource {
	private int btn_type;  //=1:file_button,=2:folder_button,=3:normal folder
	protected String name,name_ok,name_ng;
	private String thumbnailIconOK;
	private String thumbnailIconKO;
	private String thumbnailContentType;
	private String videoOk;
	private String videoKo;
	private long timer1;
	private long prevCallTime=0;
	//private VirtualVideoAction va;
	private rz_VirtualVideoActionF vab;
	private boolean call_activate=true,call_enable=true;
	private PmsConfiguration conf=PMS.getConfiguration();
	private String cname="OK";  //default btn name 
	//private boolean btnStat=true; 

	public boolean enabled,resolved;
	public int mode; 	//action mode =0:toggleButton, =1:pushButton
	public boolean ignore_activate;
	public rz_VirtualVideoActionF parent;
	public DLNAResource target;
	public String target_path;

	/**Constructor for this class. Recommended instantation includes overriding the {@link #enable()} function (example shown in the link).
	 * @param name Name that is shown via the UPNP ContentBrowser service. This field cannot be changed after the instantiation.
	 * @param enabled If true, a green tick mark is shown as thumbnail. If false, a red cross is shown. This initial value
	 * is usually changed via the {@link #enable()} function.
	 */
	public rz_VirtualVideoActionF(String name, String thumnail) {
		//super(name,null);  //should call, if params not equals to super constructor
		super(); 
		construct(name,enabled,0,0);
	}
	
	public rz_VirtualVideoActionF(String name, boolean enabled, int btype) {
		//super(name,null);  //should call, if params not equals to super constructor
		super(); 
		construct(name,enabled,0,btype);
	}

	public rz_VirtualVideoActionF(String name, boolean enabled, int mode,int btype) {
		//super(name,null);  //should call, if params not equals to super constructor
		super(); 
		construct(name,enabled,mode,btype);
	}
	
	private void construct(String name, boolean enabled, int mode, int btype) {
		this.name    = name;
		this.enabled = enabled;		//toggle status
		this.mode = mode;   		//=0:no-stat, 1:toggle_btn, =2:push_btn
		this.btn_type = btype;		//=0:auto judge,1:file_type,=2:folder_type,=3:normal folder 
		
		thumbnailContentType = HTTPResource.PNG_TYPEMIME;
		thumbnailIconOK = "images/apply-256.png";
		thumbnailIconKO = "images/button_cancel-256.png";
		this.videoOk = "videos/action_success-512.mpg";
		this.videoKo = "videos/button_cancel-512.mpg";
		timer1 = -1;
		
		//auto_judge(btn_type==0) can't exec here: b/c renderer.conf not fixed yet, do at resolve()
		if(btn_type==1) this.mflags|=DLNAResource.MF_BUTTON_ELEMENT;
		
		//setmedia here cause judge as perserV2, then becomes Direct play
		setExt(PMS.get().getAssociatedExtension("toto.mpg"));
	}
	
	@Override
	public synchronized void resolve() {
		//super.resolve();
		if(resolved) return;
		if(btn_type==0) {  //auto_judge by me
			btn_type=conf.getRZ_action_button_type();  //system define(default)
			if(getDefaultRenderer()!=null) {
				//getDefaultRenderer() will fail on construct, i.e. before resolve() called
				int bt=getDefaultRenderer().getRZ_ActionButtonType();  //per renderer define
				if(bt>0) btn_type=bt;
			}
			//PMS.dbg("rz_VirtualVideoAction.resolve: btn_type auto_judged="+btn_type+", renderer="+ getDefaultRenderer());
			/*
			if(getDefaultRenderer()==null) {
				//PMS.dbg("rz_VirtualVideoActionF.resolve: name="+getName()+", getDefaultRenderer==null");
				btn_type=1;
			}
			else {
				btn_type=getDefaultRenderer().getRZ_ActionButtonType();
			}
			*/
		}
		if(btn_type==1) {  //file_type button
			//this.sotype=DLNAResource.SO_BUTTON_ELEMENT;  //button object
			this.mflags|=DLNAResource.MF_BUTTON_ELEMENT;  //button object
			this.mflags|=MF_UNDER_TRASCO_FOLDER;   //fake up for NOT Changed player & trans_type(DIRECT)
			//this.rz_MetaTransType[0]=PMS.ENC_DIRECT;   //trasco,remux don't work well on file in jar(resource)

			// Create correct mediaInfo for the embedded .mpg videos
			// This is needed by Format.isCompatible()		
			//setmedia here(on resolve) judged as perserV1, then will be normally judged as for player
			//but by other reason, trasco,remux don't work well on file in jar(resource)
			DLNAMediaInfo mediaInfo = new DLNAMediaInfo();
			mediaInfo.setContainer("mpegps");
			mediaInfo.setMimeType("video/mpeg");
			
			ArrayList<DLNAMediaAudio> audioCodes = new ArrayList<>();
			//mediaInfo.setAudioTracksList(audioCodes);
			mediaInfo.setAudioCodes(audioCodes);
			mediaInfo.setCodecV("mpeg2");
			//mediaInfo.setWidth(512);
			//mediaInfo.setHeight(512);
			mediaInfo.setWidth(640);
			mediaInfo.setHeight(480);
			mediaInfo.setDuration(2.0);
			mediaInfo.setFrameRate("24.0");
			//mediaInfo.setAspect("1.0");
			//mediaInfo.setSize(100000);
			mediaInfo.setBitrate(1000000);
			
			mediaInfo.setMediaparsed(true);
			setMedia(mediaInfo);
		}
		else if(btn_type==2) {  //folder_type_button
			vab=new rz_VirtualVideoActionF("OK",true,0,1) { 
				//OK file under Folder_type_button
				@Override 
				public boolean enable() {
					if(parent!=null) {
						if(PMS.rz_debug>1) PMS.dbg("rz_VirtualVideoActionF.enable: parent!=null --> set parent.ignore_activate=true");
						//parent.ignore_activate=true;  //don't work well: can't judge preview/real play
						//return parent.enabled;
					}
					return true;
				}
			};
			addChild(vab);
			vab.parent=this;
		}
		resolved=true;
	}
	
	public void setTarget(DLNAResource t) {
		target=t;
	}
	public void setTargetPath(String s) {
		target_path=s;
	}
	public String getTargetPath() {
		return target_path;
	}
	
	@Override
	public int activate(int type) {
		long tim1 = System.currentTimeMillis();
		if(type!=1 || (tim1-prevCallTime) <1000) { 
			// type=1: indicate Folder Open action from renderer, called 2 times on one open why??
			return 0;
		}
		if(ignore_activate) {
			if(PMS.rz_debug>1) PMS.dbg("rz_VirtualVideoActionF.activate: ignore_activate==true --> Noop");
			ignore_activate=false;
			prevCallTime=tim1;
			return 0;
		}
		if(PMS.rz_debug>1) PMS.dbg("rz_VirtualVideoActionF.activate: exec action");
		prevCallTime=tim1;
		return action();
	}
	
	public int action() {
		//PMS.dbg("rz_VirtualVideoActionF.action: called, call_enable="+call_enable);
		call_activate=false;
		if(call_enable) {
			enabled=enable();  	//call button on/off functon
			//toString_sb=null; 	//clear button name cache
			if(PMS.rz_debug>1) PMS.dbg("rz_VirtualVideoActionF.action: enabled="+enabled);
		}
		return 0;
	}
	
	@Override
	public InputStream getInputStream() throws IOException {
		if (timer1 == -1) {
			timer1 = System.currentTimeMillis();
		} else if (System.currentTimeMillis() - timer1 < 2000) {
			timer1 = -1;
		}
		if (timer1 != -1) {
			if(btn_type==1) {  //file_type_button
				enabled = enable();
			}
		}
		//PMS.dbg("rz_VirtualVideoButtonF.getInputStream: timer1="+timer1);
		//PMS.dbg("rz_VirtualVideoButtonF.getInputStream: enabled="+enabled);
		//PMS.dbg("getInputStream: btn_type="+btn_type+", timer1="+timer1+", enabled="+enabled);
		InputStream is=getResourceInputStream(enabled ? videoOk : videoKo);
		//PMS.dbg("rz_VirtualVideoActionF: getResourceInputStream is="+is);
		return is;
	}
	
	//---- DLNAResource abstruct methods Start: must be overriden
	@Override
	public boolean isFolder() {
		if(!resolved) resolve();
		if(btn_type>=2) {
			return true;
		}
		else {
			return false;
		}
	}
	
	@Override
	public boolean isValid() {
		//setExt(PMS.get().getAssociatedExtension("toto.mpg"));
		return true;
	}
	
	public void setBtnName(String str) {
		//PMS.dbg("setBtnName: str="+str+", vabtn="+vab);
		if(vab==null) return;
		vab.setName(str);
		//vab.toString_sb=null;  //clear button name cache
	}
	public void resetBtnName() {
		if(vab==null) return;
		vab.setName("OK");
		//vab.toString_sb=null;  //clear button name cache
	}
	
	/*
	public void setBtnStat(boolean stat) {
		PMS.dbg("setBtnStat: stat="+stat+", vabtn="+vab);
		if(vab==null) return;
		vab.setBtnStat(stat);
	}
	
	public void setStat(boolean stat) {
		btnStat=stat;
	}
	*/
	
	@Override 
	public String getName() {
		//PMS.dbg("rz_VirtualVideoActionF.getName: mode="+mode);
		if(mode==1) {  //toggle button 
			//PMS.dbg("rz_VirtualVideoActionF.getName: mode=ToggleBtn, enabled="+enabled);
			if(enabled) {
				return "[*]"+name;  //Toggle ON
			}
			else {
				return "[-]"+name;  //Toggle OFF
			}
		}
		else if(mode==2) {
			return "[!]"+name;  //Push button 
		}
		else {
			return name;   //no status button
		}
	}
	
	public String getDpName() {
		return name;
	}
	public String getBaseName() {
		return name;
	}
	
	@Override
	public long length() {
		return -1;  //must be -1, otherwise fail on play. wny??
	}
	public long lastModified() {
		return 0;
	}
	@Override
	public String getSystemName() {
		return "resources/"+(enabled ? videoOk : videoKo);
		//return getName();
	}
	

	@Override
	public boolean isTranscodeFolderAvailable() {
		return false;
	}
	
	@Override
	public String getThumbnailContentType() {
		return thumbnailContentType;
	}
	@Override
	public InputStream getThumbnailInputStream() {
		return getResourceInputStream(enabled ? thumbnailIconOK : thumbnailIconKO);
	}

	//---- DLNAResource abstruct methods End :

	/**Prototype. This function is called by {@link #getInputStream()} and is the core of this class.
	 * The main purpose of this function is toggle a boolean variable somewhere. 
	 * The value of that boolean variable is shown then as either a green tick mark or a red cross.
	 * However, this is just a cosmetic thing. Any Java code can be executed in this function, not only toggling a boolean variable.
	 * Recommended way to instantiate this class is as follows:
	 * <pre> VirtualFolder vf;
	 * [...]
	 * vf.addChild(new VirtualVideoAction(Messages.getString("PMS.3"), configuration.isMencoderNoOutOfSync()) {
	 *   public boolean enable() {
	 *   configuration.setMencoderNoOutOfSync(!configuration.isMencoderNoOutOfSync());
	 *   return configuration.isMencoderNoOutOfSync();
	 *   }
	 * }); </pre>
	 * @return If true, a green tick mark is shown as thumbnail. If false, a red cross is shown.
	 */
	//public abstract boolean enable();
	public boolean enable() {
		call_enable=false;  //to avoid call-loop
		if(call_activate) {
			int rc=activate(1);
			boolean brc=(rc==0?true:false);
			//PMS.dbg("rz_VirtualVideoButtonF.enable: call activate(1), rc="+rc+" --> return "+brc );
			return brc;
		}
		else {
			//PMS.dbg("rz_VirtualVideoButtonF.enable: --> return true");
			return true;
		}
	}
	
	@Override
	public String toString (RendererConfiguration mediaRenderer) {
		toString_sb=null;
		return super.toString(mediaRenderer);
	}
	
}
