//
// https://www.ramecera.it/myscrewdriver.html
// e-mail: screwdriver@ramecera.it
//
/* This program and the accompanying materials are made available under
 * the terms of the Eclipse Public License v1.0 which accompanies this
 * distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html */

package it.ramecera.salad.file;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import it.ramecera.salad.everyday.Mix;

/**
 * <p>
 * Processing of lists of files contained in a directory.
 * </p>
 * <p>
 * Company: Ramecera™<br>
 * Creation date: 2020-04-09<br>
 * Last updated: 2020-04-19<br>
 * </p>
 * <p>
 * Changes:<br>
 * </p>
 * 
 * @author M. Maglioni */

public class Folder {

	/** list of the files, with some their properties */
	public List<FileBase> fbE = new ArrayList<FileBase>();

	/**
	 * <p>
	 * Production of the list of files of a directory, filtered
	 * according to a pattern. It differs from the <b>listFile</b>
	 * method in that it produces an array of File objects and not
	 * simply their names.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @return array of strings with the found files
	 * @param filter the pattern to filter the files, according to the
	 *        codes of the class java.util.regex.Pattern.
	 * @param y the path where to search for files */
	public File[] fileObjects(final String filter, final String y) {
		// if necessary, I put a slash in the queue
		String y1 = Mix.dress_C(y);
		File f = new File(y);
		if (!f.exists() || !f.isDirectory()) // quality control
			return null;
		String[] s = f.list(Mix.fileFilter(filter));
		File[] of = new File[s.length];
		for (int j = 0; j < s.length; j++) {
			of[j] = new File(y1 + s[j]);
		}
		return of;
	}

	/**
	 * <p>
	 * Production of the list of files of a directory, filtered
	 * according to a pattern. It differs from the <b>fileObjects</b>
	 * method in that it produces an array of file objects sorted by
	 * "Last update", and not simply their names.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @return array of strings with the found files
	 * @param filter the pattern to filter the files, according to the
	 *        codes of the class java.util.regex.Pattern.
	 * @param y the path where to search for files */
	public List<File> oggettiFileOrdinaModi(final String filter,
			final String y) {
		// if necessary, I put a slash in the queue
		String y1 = Mix.dress_CU(y);
		File f = new File(y);
		if (!f.exists() || !f.isDirectory()) // quality control
			return null;
		String[] s = f.list(Mix.fileFilter(filter));
		List<File> of = new ArrayList<File>();
		for (String t : s) {
			of.add(new File(y1 + t));
		}
		Collections.sort(of, new MyComparatorFileModi());
		return of;
	}

	/**
	 * <p>
	 * Production of the list of subdirectories of a directory. It
	 * differs from the <b>objectsFile</b> method in that it produces an
	 * array of File objects sorted by Last update, and not simply their
	 * names.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @return array of strings with directories found according to the
	 *         codes of the java.util.regex.Pattern class.
	 * @param y the path where to search for files */
	public List<File> dirObjects(final String y) {
		// if necessary, I put a slash in the queue
		String y1 = Mix.dress_CU(y);
		File f = new File(y);
		// if the input directory does not exist, or is not a directory
		// ...
		if (!f.exists() || !f.isDirectory()) // quality control
			return null; // nothing is done about it
		String[] s = f.list(Mix.filterDirectory());
		List<File> of = new ArrayList<File>();
		for (String t : s) {
			of.add(new File(y1 + t));
		}
		return of;
	}

	/**
	 * <p>
	 * Production of the list of subdirectories of a directory. It
	 * differs from the <b>objectsFile</b> method in that it produces an
	 * array of File objects sorted by Last update, and not simply their
	 * names.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @return array of strings with files found according to the codes
	 *         of the java.util.regex.Pattern class.
	 * @param y the path where to search for files */
	public List<File> oggettiDireOrdinaModi(final String y) {
		// if necessary, I put a slash in the queue
		String y1 = Mix.dress_CU(y);
		File f = new File(y);
		// if the input directory does not exist, or is not a directory
		// ...
		if (!f.exists() || !f.isDirectory()) // quality control
			return null; // nothing is done about it
		String[] s = f.list(Mix.filterDirectory());
		List<File> of = new ArrayList<File>();
		for (String t : s) {
			of.add(new File(y1 + t));
		}
		Collections.sort(of, new MyComparatorFileModi());
		return of;
	}

	/**
	 * <p>
	 * Production of the list of files of a directory, filtered
	 * according to a pattern. It differs from the <b>objectsFile</b>
	 * method in that it produces an array of File objects sorted by
	 * Last update, and not simply their names.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @return array of strings with the found files
	 * @param filter the pattern to filter the files, according to the
	 *        codes of the class java.util.regex.Pattern.
	 * @param y the path where to search for files */
	public List<File> oggettiFileOrdinaAlfa(final String filter,
			final String y) {
		// if necessary, I put a slash in the queue
		String y1 = Mix.dress_CU(y);
		File f = new File(y);
		if (!f.exists() || !f.isDirectory()) // quality control
			return null;
		String[] s = f.list(Mix.fileFilter(filter));
		List<File> of = new ArrayList<File>();
		for (String t : s) {
			of.add(new File(y1 + t));
		}
		Collections.sort(of, new MyComparatorFileAlfa());
		return of;
	}

	/**
	 * <p>
	 * Production of the list of subdirectories of a directory. It
	 * differs from the <b>ObjectsDire</b> method in that it produces an
	 * array of File objects sorted by date of last modification, and
	 * not simply their names.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @return array of strings with files found according to the codes
	 *         of the java.util.regex.Pattern class.
	 * @param y the path where to search for files */
	public List<File> oggettiDireOrdinaAlfa(final String y) {
		// if necessary, I put a slash in the queue
		String y1 = Mix.dress_CU(y);
		File f = new File(y);
		// if the input directory does not exist, or is not a directory
		// ...
		if (!f.exists() || !f.isDirectory()) // quality control
			return null; // nothing is done about it
		String[] s = f.list(Mix.filterDirectory());
		List<File> of = new ArrayList<File>();
		for (String t : s) {
			of.add(new File(y1 + t));
		}
		Collections.sort(of, new MyComparatorFileAlfa());
		return of;
	}

	/**
	 * <p>
	 * Production of the list of subdirectories of a directory. It
	 * differs from the <b>ObjectsDire</b> method in that it produces an
	 * array of File objects sorted by date of last modification, and
	 * not simply their names.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @return array of strings with files found according to the codes
	 *         of the java.util.regex.Pattern class.
	 * @param y the path where to search for files
	 * @param filter filter for selecting files */
	public List<File> oggettiDireOrdinaAlfa(final String filter,
			final String y) {

		// if necessary, I put a slash in the queue
		String y1 = Mix.dress_CU(y);
		File f = new File(y);
		// if the input directory does not exist, or is not a directory
		// ...
		if (!f.exists() || !f.isDirectory()) // quality control
			return null; // nothing is done about it
		String[] s = f.list(Mix.filtroDirectory(filter));
		List<File> of = new ArrayList<File>();
		for (String t : s) {
			of.add(new File(y1 + t));
		}
		Collections.sort(of, new MyComparatorFileAlfa());
		return of;
	}

	/**
	 * <p>
	 * Production of the list of files of a directory, filtered
	 * according to a pattern.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @return array of strings with the found files
	 * @param filter the pattern to filter the files, according to the
	 *        codes of the class java.util.regex.Pattern.
	 * @param y the path where to search for files */
	public String[] elencoFile(final String filter, final String y) {
		File f = new File(y);
		if (!f.exists() || !f.isDirectory()) // quality control
			return null;
		return f.list(Mix.fileFilter(filter));
	}

	/**
	 * <p>
	 * Production of the list of files of a system of directories.
	 * </p>
	 * <p>
	 * Company: Ramecera™<br>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09<br>
	 * </p>
	 * 
	 * @param y input directory
	 * @return the file list */
	public List<FileBase> fileImmersion(final String y) {
		int profondita = 0;
		ArrayList<FileBase> fbE = new ArrayList<FileBase>();
		File f = new File(y);
		if (!f.exists() || !f.isDirectory()) {
			return null;
		}
		fbE = new ArrayList<FileBase>();
		fileAccumulation(y, fbE, profondita);
		return fbE;
	}

	private void fileAccumulation(final String y, List<FileBase> fbE,
			int profondita) {
		File[] aE = fileObjects("\\p{ASCII}+", y);
		FileBase fb = null;
		for (File a : aE) {
			if (a.isDirectory()) {
				continue;
			}
			fb = Mix.analizzaPathBase(a);
			fb.depth = profondita;
			fbE.add(fb);
		}
		profondita++;
		List<File> bE = dirObjects(y);
		for (File c : bE) {
			fileAccumulation(c.getPath(), fbE, profondita);
		}
	}

	/**
	 * <p>
	 * Production of the list of directories of a system of directories,
	 * filtered according to a pattern.
	 * </p>
	 * <p>
	 * Company: Ramecera™<br>
	 * Creation date: 2020-09-08<br>
	 * Last updated: 2020-09-08<br>
	 * </p>
	 * 
	 * @param y input directory
	 * @param pattern obvious
	 * @return the file list */
	public List<String> dirImmersion(final String y,
			final String pattern) {
		int depth = 0;
		ArrayList<String> fbE = new ArrayList<String>();
		File f = new File(y);
		if (!f.exists() || !f.isDirectory()) {
			return null;
		}
		fbE = new ArrayList<String>();
		dirAccumulation(y, fbE, depth, pattern);
		return fbE;
	}

	private void dirAccumulation(final String y, List<String> dirE,
			int depth, final String pattern) {
		File[] aE = fileObjects(pattern, y);
		for (File a : aE) {
			if (a.isDirectory()) {
				dirE.add(a.getPath());
			}
		}
		depth++;
		List<File> bE = dirObjects(y);
		for (File c : bE) {
			dirAccumulation(c.getPath(), dirE, depth, pattern);
		}
	}

	/** Class needed to sort files by date */
	class MyComparatorFileModi implements Comparator<File> {

		/**
		 * <p>
		 * Method of comparison based on the date of the last
		 * modification of the file.
		 * </p>
		 * <p>
		 * Creation date: 2020-04-09<br>
		 * Last updated: 2020-04-09
		 * </p>
		 * <p>
		 * Changes:<br>
		 * </p>
		 * 
		 * @param f1 first object (file)
		 * @param f2 second object (file)
		 * @return minor = -1, major = 1 or equal = 0 */
		@Override
		public int compare(File f1, File f2) {
			if (f2.lastModified() == f1.lastModified())
				return 0;
			else if (f2.lastModified() > f1.lastModified())
				return 1;
			else
				return -1;
		}
	}

	/** Class needed to sort files alphabetically by name */
	class MyComparatorFileAlfa implements Comparator<File> {

		/**
		 * <p>
		 * Method of comparison based on the date of the last
		 * modification of the file.
		 * </p>
		 * <p>
		 * Creation date: 2020-04-09<br>
		 * Last updated: 2020-04-09
		 * </p>
		 * <p>
		 * Changes:<br>
		 * </p>
		 * 
		 * @param f1 first object (file)
		 * @param f2 second object (file)
		 * @return minor = -1, major = 1 or equal = 0 */
		@Override
		public int compare(File f1, File f2) {
			return f1.getName().compareTo(f2.getName());
		}
	}
}
