//PRET-Extractor
//Copyright (c) 2013 Tetsuya Kanda
//
//http://sel.ist.osaka-u.ac.jp/pret/
//
//Permission is hereby granted, free of charge, to any person obtaining
//a copy of this software and associated documentation files (the
//"Software"), to deal in the Software without restriction, including
//without limitation the rights to use, copy, modify, merge, publish,
//distribute, sublicense, and/or sell copies of the Software, and to
//permit persons to whom the Software is furnished to do so, subject to
//the following conditions:
//
//The above copyright notice and this permission notice shall be
//included in all copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
//MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
//LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
//OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
//WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

package jp.ac.osaka_u.ist.sel.pret.engine;

import gnu.trove.map.TIntObjectMap;
import gnu.trove.map.hash.TIntObjectHashMap;

import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

import jp.ac.osaka_u.ist.sel.pret.engine.data.DirectoryInfo;
import jp.ac.osaka_u.ist.sel.pret.engine.data.FileInfo;
import jp.ac.osaka_u.ist.sel.pret.engine.preprocess.Preprocessor;
import jp.ac.osaka_u.ist.sel.pret.engine.preprocess.PreprocessorFactory;
import jp.ac.osaka_u.ist.sel.pret.util.ParaRun;

/**
 * read project
 * 
 * @author t-kanda
 * 
 */
public class FileInfoMaker {

	private int nextFileId;
	private int projectId;
	private Path tmp;
	private List<Maker> targets;

	private TIntObjectMap<FileInfo> newFiles;

	/**
	 * set up for reading project
	 * 
	 * @param projectId
	 *            project ID
	 * @param nextFileId
	 *            file ID for the next input
	 * @param projectTmp
	 *            tmp directory
	 */
	public FileInfoMaker(int projectId, int nextFileId, Path projectTmp) {
		this.tmp = projectTmp;
		this.projectId = projectId;
		this.nextFileId = nextFileId;
		newFiles = new TIntObjectHashMap<>();
		targets = new ArrayList<>();
	}

	/**
	 * do analysis
	 * 
	 * @return map (file id - file information)
	 */
	public TIntObjectMap<FileInfo> make() {
		ParaRun<Maker> pararun = new ParaRun<>();
		pararun.addAll(targets);
		newFiles = new TIntObjectHashMap<>();
		pararun.run();

		return newFiles;
	}

	/**
	 * add target file (just list up)
	 * 
	 * @param target
	 *            target source file
	 * @param parent
	 *            parent directory information
	 * @param type
	 *            type charactor
	 */
	public void add(Path target, DirectoryInfo parent, char type) {
		targets.add(new Maker(target, nextFileId++, parent, type));
	}

	/**
	 * class for reading files
	 * 
	 * @author t-kanda
	 * 
	 */
	private class Maker implements Runnable {

		Path path;
		int fileId;
		DirectoryInfo parent;
		char type;

		public Maker(Path path, int fileId, DirectoryInfo parent, char type) {
			this.path = path;
			this.fileId = fileId;
			this.parent = parent;
			this.type = type;
		}

		@Override
		public void run() {

			FileInfo fi = new FileInfo(fileId, projectId, path.toUri(), parent, type);
			Preprocessor pp = PreprocessorFactory.create(type, tmp);
			pp.preprocessForCalcSimilarity(fi);
			pp.preprocessForDiff(fi);
			synchronized (newFiles) {
				newFiles.put(fileId, fi);
			}
		}
	}

}
