/*
 * 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.
 */
//-----------------------------------------------------------------------------
// Folder for watched objs
//-----------------------------------------------------------------------------
package net.pms.dlna;

//import java.io.*;
import java.io.File;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;

import net.pms.PMS;
import net.pms.configuration.PmsConfiguration;
import net.pms.configuration.RendererConfiguration;
import net.pms.configuration.MapFileConfiguration;
import net.pms.dlna.virtual.VirtualFolder;
import net.pms.dlna.rz_PlayMetaFile;
import net.pms.dlna.rz_Resume;
import net.pms.dlna.ZippedFile;
import net.pms.dlna.ZippedEntry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class  rz_WatchedFolder extends MapFile {
	private static final Logger logger = LoggerFactory.getLogger(rz_WatchedFolder.class);
	private boolean resolved=false;
	private String thumbnailIcon=null;
	public rz_WatchedVirtualFolder delFolder;
	private rz_WatchedVirtualFolder delFolderAll;
	private int norefresh=0;
	private boolean active;
	private boolean childUpdate;
	public List<String> srcHash_list = new ArrayList<String>();
	public boolean filter;
	private static File baseFolder;
	private static PmsConfiguration config=PMS.getConfiguration();
	private int menu_type=PMS.getConfiguration().getRZ_menu_type();
	public DLNAResource dlna_tg;	//target folder's DLNAobject
	
	public rz_WatchedFolder(File folder, String name, boolean filter) {  //for all watched
		if(!folder.isDirectory()) {
			return;
		}
		sotype=SO_WATCHED_FOLDER;
		//baseFolder=PMS.rz_watched.getBaseFolder();
		baseFolder=folder;
		if(name!=null) getConf().setName(name);
		if(filter) {
			this.filter=true;
			String hash=""+folder.hashCode();
			srcHash_list.add(hash);
			getConf().getFiles().add(baseFolder);
			setLastmodified(baseFolder.lastModified());
		}
		else {
			this.filter=false;
			getConf().getFiles().add(folder);
			setLastmodified(folder.lastModified());
		}
	}
	
	public rz_WatchedFolder(DLNAResource dlna, String name, boolean filter) { //for perFolder watched
		
		if(!dlna.isFolder()) return;
		if(!(dlna instanceof MapFile) && dlna.getResumePath()==null) {
			return;
		}
		if(dlna instanceof ZippedFile) {
			//currentry not supported
			return;
		}
		dlna_tg=dlna;
		sotype=SO_WATCHED_FOLDER;
		if(baseFolder==null) {
			//baseFolder=PMS.rz_Watched.getBaseFolder();  //must be called after 
			logger.error("rz_WatchedFolder: baseFolder is null, must be called after rz_WatchedFolder(File folder,..)");
			return;
		}
		if(name!=null) getConf().setName(name);
		getConf().getFiles().add(baseFolder);
		setLastmodified(baseFolder.lastModified());
		String path,hash;
		
		if(filter) {
			this.filter=true;
			if(dlna instanceof MapFile) {  //real folder
				for(File file : ((MapFile)dlna).getConf().getFiles()) {
					if (file != null && file.canRead()) {
						if(file.isDirectory()) {  // real/virtual folders
							if(file.getName().equals("VIDEO_TS")) { // roufgh check, tobe refiled
								path=file.getAbsolutePath()+"/"+file.lastModified();
								file=new File(path);
							}
							hash=""+file.hashCode();
						}
						else {  //may be files under virtual folder
							hash=rz_Resume.getResumeFileName(file,null);
						}
						srcHash_list.add(hash);
					}
				}
			}
			else { //virtual_folder (playlist/webfolder etc)
				//path=dlna.getSrcPath();
				hash=null;
				if((dlna.mflags & DLNAResource.MF_WEB_FOLDER)!=0) { //webFolder
					if(PMS.rz_resume_per_folder_web==0) {  // RESUME_PER_FOLDER disp all web_objs, instead of per webFolders
						hash=rz_Resume.HASH_PREFIX_WEB;
					}
				}
				if(hash==null) {
					path=dlna.getResumePath();
					if(path!=null) {
						File file=new File(path);
						if(file.getName().equals("VIDEO_TS")) { // roufgh check, tobe refiled
							path=file.getAbsolutePath()+"/"+file.lastModified();
							file=new File(path);
						}
						hash=""+file.hashCode();
						//PMS.dbg("rz_WatchedFolder: called, seems playlist, path="+path+", hash="+hash);
					}
				}
				if(hash!=null) srcHash_list.add(hash);
			}
		}
	}
	
	@Override
	public boolean isFolder() {
		return true;
	}
	
	@Override
	public boolean isTranscodeFolderAvailable() {
		return true;
	}

	@Override
	public void discoverChildren() {
		//1st time
		//PMS.dbg("rz_WatchedFolder.discoverChildren: called");
		long tim1=System.currentTimeMillis();
		if(PMS.rz_trace>0) PMS.trace("rz_WatchedFolder.discoverChildren: Start");
		super.discoverChildren();
		long tim2=System.currentTimeMillis();
		if(PMS.rz_trace>0) PMS.trace("rz_WatchedFolder.discoverChildren: End, elapsed="+(tim2-tim1));
	}
	
	
	@Override
	public boolean analyzeChildren(int count) {
		//1st time
		long tim1=System.currentTimeMillis();
		
		if(PMS.rz_trace>0) PMS.trace("rz_WatchedFolder.analyzeChildren: Start, count="+count);
		boolean rc=super.analyzeChildren(count);
		createDelFolders(false);
		
		long tim2=System.currentTimeMillis();
		if(PMS.rz_trace>0) PMS.trace("rz_WatchedFolder.analyzeChildren: End, elapsed="+(tim2-tim1));	//regzamod
		return rc;
	}

	
	@Override
	public void refreshChildren() {
		//2nd time or after 
		long tim1=System.currentTimeMillis();
		if(PMS.rz_trace>0) PMS.trace("rz_WatchedFolder.refreshChildren: Start");
		
		if(false) {  //fast??
			ClearFolder(); //for whole re-create children
			delFolder=null;
			discoverChildren();
			analyzeChildren(-1);
		}
		else {  //slow??
			super.refreshChildren(); 
		}
		if(active) {
			refreshDelFolders();
			active=false;
		}
		long tim2=System.currentTimeMillis();
		if(PMS.rz_trace>0) PMS.trace("rz_WatchedFolder.refreshChildren: End, elapsed="+(tim2-tim1));
	}
	
	public int activate(int type) {
		if(PMS.rz_debug>1) PMS.dbg("rz_WatchedFolder.activate: Start");

		//PMS.dbg("====>> rz_WatchedFolder.activate: called, childUpdate="+childUpdate);
		if(type>=0) {
			active=true;
		}
		if(false && childUpdate) {
			//PMS.dbg("====>> rz_WatchedFolder.activate: call refreshDelFolders");
			refreshDelFolders();
			childUpdate=false;
		}
		
		if(PMS.rz_debug>1) PMS.dbg("rz_WatchedFolder.activate: End");
		return 0;
	}
		
	public void needRefresh(boolean b) {
		//PMS.dbg("====> rz_WatchedFolder.needRefresh: called childUpdate set to true");
		active=false;
		childUpdate=true;
		//norefresh=1;
	}
	
	@Override
	public boolean isRefreshNeeded() {
		if(PMS.rz_debug>1) PMS.dbg("rz_WatchedFolder.isRefreshNeeded: Start");
		boolean rc;
		rc=super.isRefreshNeeded();
		//PMS.dbg("rz_WatchedFolder.isRefreshNeeded: return "+rc);
		if(PMS.rz_debug>1) PMS.dbg("rz_WatchedFolder.isRefreshNeeded: End rc="+rc);
		return rc;
	}
	
	public void delAllFiles() {  //delete all target watched files
		if(PMS.rz_debug>1) PMS.dbg("rz_WatchedFolder.delAllFiles: Start");
		List<File> files= getFileList();
		for(File f : files) {
			f.delete();
		}
		if(PMS.rz_debug>1) PMS.dbg("rz_WatchedFolder.delAllFiles: End");
	}

	@Override
	public List<File> getFileList() {
		long tim1=System.currentTimeMillis();
		if(PMS.rz_trace>0) PMS.trace("rz_WatchedFolder.getFileList: Start");

		//PMS.dbg("rz_WatchedFolder.getFileList: filter="+filter+", srcPath="+srcPath+", srcHash="+srcHash);
		List<File> out = new ArrayList<File>();
		File[] rfiles=baseFolder.listFiles();
		//PMS.dbg("rfiles="+rfiles);
		String rname;
		if(!filter) {
			for (File file : rfiles) {
				if (file != null) {
					if(file.isFile() && file.getName().endsWith(PMS.rz_ResumeFileSuffix)) {
						out.add(file);
					}
				}
			}
		}
		else if(dlna_tg!=null && dlna_tg.sotype==SO_PLAYLIST) {
			for (DLNAResource ch : dlna_tg.getChildren()) {
				if(ch.isFolder()) continue;
				rname=rz_Resume.getResumeObjName(ch);
				//PMS.dbg("----- getFileList: rname="+rname);
				if(rname==null) continue;
				for(File file: rfiles) {
					//PMS.dbg("getFileList: fname="+file.getName());
					if(file.getName().contains(rname)) {
						out.add(file);
					}
				}
			}
		}
		else {
			//PMS.dbg("r_WatchedFolder.getFileList: baseFolder="+baseFolder);
			for (File file : rfiles) {
				if (file != null && file.isFile()) {
					//PMS.dbg("r_WatchedFolder.getFileList: file="+file);
					String name=file.getName();
					for(String hash: srcHash_list) {
						if(name.contains(hash)) {
							out.add(file);
						}
					}
				}
			}
		}
		if(PMS.rz_trace>0) {
			long tim2=System.currentTimeMillis();
			PMS.trace("rz_WatchedFolder.getFileList: End, count="
			+(out==null?"0":out.size())
			+", elapsed="+(tim2-tim1));
		}
		return out;
	}
	
	public void createDelFolders(boolean init) {
		//---- create virtualFolder for delete-action of watched files)
		long tim1=System.currentTimeMillis();
		if(PMS.rz_trace>0) PMS.trace("rz_WatchedFolder.createDelFolders: Start");

		if(getChildren().size()<=0) {
			//return;
		}
		
		//File will be searched primary in *.jar, secondry on real directoriy
		//File okmovie=new File("videos/action_success-512.mpg");
		//rz_PlayMetaFile pxm;
		rz_WatchedVirtualFolder vf;
		
		//---- for delete-watched action
		if(delFolder==null) {
			delFolder=new rz_WatchedVirtualFolder("#- WATCHED DELETE -#",1);
			delFolder.setRfType(rz_WatchedVirtualFolder.RF_DEL_WATCHED_BASE);
			delFolder.setWatchedBase(this);
			delFolder.setSerialId(DLNAResource.MENU_ORD_WATCHED_DEL);
			delFolder.sort_immune=0;
			VirtualFolder pa;
			if(menu_type>=2) {  // newType
				pa=getCtlFolder(true,1);
			}
			else {
				pa=getTranscodeFolder(true,-1);
			}
			pa.doSort=true;
			//pa.addChildInternal(delFolder);	
			//addChildInternal(delFolder);  //can't disp activate_icon
			pa.addChild(delFolder);
			if(init) {
				if(PMS.rz_trace>0) {
					long tim2=System.currentTimeMillis();
					PMS.trace("rz_WatchedFolder.createDelFolders: End, already inited-1 elapsed="+(tim2-tim1));
				}
				return;
			}
		}
		else if(init){
			if(PMS.rz_trace>0) {
				long tim2=System.currentTimeMillis();
				PMS.trace("rz_WatchedFolder.createDelFolders: End, already inited-2 elapsed="+(tim2-tim1));
			}
		 	return;
		}
		else {
			//PMS.dbg("rz_WatchedFolder.createDelFolders: getChildren().clear()");
			delFolder.activate(1);
			delFolder.getChildren().clear();
			delFolder.initLastChildrenId();
			delFolder.deleteMenus();
		}
		//---- create folder for delete-part-action
		VirtualFolder vfp=new VirtualFolder("#- WATCHED DELETE MULTI -#",null);
		vfp.sort_immune=1;
		delFolder.addChild(vfp);	

		//---- create folder for delete-all-action
		vf=new rz_WatchedVirtualFolder("#- WATCHED DELETE ALL -#");
		vf.setRfType(rz_WatchedVirtualFolder.RF_DEL_WATCHED_ALL);
		vf.setParentRF(this);
		vf.setParentVF(delFolder);
		vf.setWatchedBase(this);
		//vf.sort_immune=1;
		//delFolder.addChild(vf);	
		vfp.addChild(vf);	
		//---- create folder for delete-all-action
		vf=new rz_WatchedVirtualFolder("#- WATCHED DELETE OLD (Before 1 Week) -#");
		vf.setRfType(rz_WatchedVirtualFolder.RF_DEL_WATCHED_PART);
		vf.setParams(7);  // 7 days (1 week)
		vf.setParentRF(this);
		vf.setParentVF(delFolder);
		vf.setWatchedBase(this);
		vfp.addChild(vf);	
		//---- create folder for delete-all-action
		vf=new rz_WatchedVirtualFolder("#- WATCHED DELETE OLD (Before 1 Month) -#");
		vf.setRfType(rz_WatchedVirtualFolder.RF_DEL_WATCHED_PART);
		vf.setParams(30);// 30 days (1 month)
		vf.setParentRF(this);
		vf.setParentVF(delFolder);
		vf.setWatchedBase(this);
		vfp.addChild(vf);	
		//---- create folder for delete-all-action
		vf=new rz_WatchedVirtualFolder("#- WATCHED DELETE OLD (Before 3 Month) -#");
		vf.setRfType(rz_WatchedVirtualFolder.RF_DEL_WATCHED_PART);
		vf.setParams(90);
		vf.setParentRF(this);
		vf.setParentVF(delFolder);
		vf.setWatchedBase(this);
		vfp.addChild(vf);	
		//---- create folder for delete-all-action
		vf=new rz_WatchedVirtualFolder("#- WATCHED DELETE OLD (Before 6 Month) -#");
		vf.setRfType(rz_WatchedVirtualFolder.RF_DEL_WATCHED_PART);
		vf.setParams(180);
		vf.setParentRF(this);
		vf.setParentVF(delFolder);
		vf.setWatchedBase(this);
		vfp.addChild(vf);	
		//---- create folder for delete-all-action
		vf=new rz_WatchedVirtualFolder("#- WATCHED DELETE OLD (Before 1 Year) -#");
		vf.setRfType(rz_WatchedVirtualFolder.RF_DEL_WATCHED_PART);
		vf.setParams(365);
		vf.setParentRF(this);
		vf.setParentVF(delFolder);
		vf.setWatchedBase(this);
		vfp.addChild(vf);	
		
		//---- create folders for delete-single-action
		for(DLNAResource ch: getChildren()) {
			if(!ch.isFolder() && ch.rz_Metafile!=null) {
				//create folder for delete-action per watched-files
				vf=new rz_WatchedVirtualFolder("DEL- "+ch.getName());
				vf.setRfType(rz_WatchedVirtualFolder.RF_DEL_WATCHED_SGL);
				vf.setSrcObj(ch);
				if(ch.meta_type!=2) {
					if(PMS.rz_debug>0) PMS.dbg("WatchedFolder: Something wrong! obj.meta_type!=2: force =2, obj="+ch.getName0());
					ch.meta_type=2;
				}
				vf.setParentRF(this);
				vf.setParentVF(delFolder);
				vf.setWatchedBase(this);
				vf.setDispDate(ch.getDispDate());
				vf.rz_Metafile=ch.rz_Metafile;
				delFolder.addChild(vf);
			}
		}
		//PMS.dbg("createDelFolders: set doSort=true, sort_type="+delFolder.getSortType());
		delFolder.sort_enabled=true;
		delFolder.doSort=true;
		//dlnaListSort(delFolder.getChildren(),delFolder.getSortType());
		if(PMS.rz_trace>0) {
			long tim2=System.currentTimeMillis();
			PMS.trace("rz_WatchedFolder.createDelFolders: End, elapsed="+(tim2-tim1));
		}

	}
	
	private void refreshDelFolders() {
		//easyway but heavy
		if(PMS.rz_debug>1) PMS.dbg("rz_WatchedFolder.refreshDelFolders: Start");
		createDelFolders(false);
		if(PMS.rz_debug>1) PMS.dbg("rz_WatchedFolder.refreshDelFolders: End");
	}
	
	@Override
	public int getSortType() {	//regzamod add
		//PMS.dbg("rz_WatchedFolder.getSortType(): rz_MetaSortType="+rz_MetaSortType
		//	+", PMS.rz_watched_sort_type="+PMS.rz_watched_sort_type);
		if(rz_MetaSortType>=0) {
			return rz_MetaSortType;
		}
		else if(PMS.rz_watched_sort_type==PMS.SORT_DEFAULT) {
			return PMS.getConfiguration().getSortMethod();
		}
		else {
			return PMS.rz_watched_sort_type;
		}
	}
	
	public void res_delete (File f) {
		//f.delete();
		if(f==null || baseFolder==null) return;
		File dest=new File(baseFolder.getPath() + PMS.FSEP + f.getName());
		if(dest.exists()) {
			dest.delete(); 
		}
	}

}