//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.
//http://sel.ist.osaka-u.ac.jp/~t-kanda/
//
//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;

import gnu.trove.map.TObjectCharMap;
import gnu.trove.map.hash.TObjectCharHashMap;

import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Objects;

import jp.ac.osaka_u.ist.sel.pret.util.EncodeDetector;
import jp.ac.osaka_u.ist.sel.pret.util.ParaRun;

import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

public class OptionContainer {

	private int diffType = 0;
	private Path diffCommand;
	private Path graphvizPath;
	private TObjectCharMap<String> types;
	private boolean onMemory, skip;
	private Path tmp, result;

	/**
	 * parse args and get option values
	 * 
	 * @param args
	 */
	public OptionContainer(String args[]) {

		Options options = new Options();
		OptionBuilder.withLongOpt("diff");
		OptionBuilder.hasArgs();
		OptionBuilder.withArgName("diff command");
		options.addOption(OptionBuilder.create());

		OptionBuilder.withLongOpt("m");
		OptionBuilder.hasOptionalArg();
		OptionBuilder.withDescription("save similarity and/or diff on memory");
		options.addOption(OptionBuilder.create());

		OptionBuilder.withLongOpt("graph");
		OptionBuilder.hasArg();
		OptionBuilder.withArgName("dot command");
		options.addOption(OptionBuilder.create());

		OptionBuilder.withLongOpt("type");
		OptionBuilder.isRequired();
		OptionBuilder.hasArg();
		OptionBuilder.withArgName("type");
		options.addOption(OptionBuilder.create());

		OptionBuilder.withLongOpt("tmp");
		OptionBuilder.hasArg();
		OptionBuilder.withArgName("temp directory");
		options.addOption(OptionBuilder.create());

		OptionBuilder.withLongOpt("result");
		OptionBuilder.hasArg();
		OptionBuilder.withArgName("result output directory");
		options.addOption(OptionBuilder.create());

		OptionBuilder.withLongOpt("thread");
		OptionBuilder.hasOptionalArg();
		OptionBuilder.withDescription("thread");
		options.addOption(OptionBuilder.create());

		CommandLineParser parser = new BasicParser();
		CommandLine cmd;
		try {
			cmd = parser.parse(options, args);
		} catch (ParseException e) {
			System.err.println("PARSE ARGS ERROR");
			return;
		}

		FileSystem fs = FileSystems.getDefault();

		if (cmd.hasOption("diff")) {
			diffType = Integer.parseInt(cmd.getOptionValues("diff")[0]);
			diffCommand = cmd.getOptionValues("diff").length > 0 ? fs.getPath(cmd.getOptionValues("diff")[0]) : null;
		}

		if (cmd.hasOption("graph")) {
			graphvizPath = fs.getPath(cmd.getOptionValue("graph"));
			if (!Files.isExecutable(graphvizPath)) {
				graphvizPath = null;
			}
		}

		if (cmd.hasOption("type")) {
			types = new TObjectCharHashMap<String>();
			readTypeConf(fs.getPath(cmd.getOptionValue("type")));
		}

		if (cmd.hasOption("tmp")) {
			tmp = fs.getPath(cmd.getOptionValue("tmp"));
		} else {
			tmp = fs.getPath(".");
		}

		if (cmd.hasOption("result")) {
			result = fs.getPath(cmd.getOptionValue("result"));
		} else {
			result = tmp;
		}

		if (cmd.hasOption("thread")) {
			ParaRun.para = Integer.parseInt(cmd.getOptionValue("thread"));
		} else {
			ParaRun.para = 1;
		}

		if (cmd.hasOption('m')) {
			onMemory = true;
			// if (cmd.getOptionValue('m') != null && cmd.getOptionValue('m').equals("skip")) {
			if (Objects.equals(cmd.getOptionValue('m'), ("skip"))) {
				skip = true;
			}
		}
	}

	private void readTypeConf(Path path) {

		if (path == null || Files.isDirectory(path)) {
			types.put("", 'D');
			return;
		}

		try {
			for (String line : Files.readAllLines(path, EncodeDetector.charset(path))) {
				String[] test = line.split(",");
				if (test.length > 1) {
					types.put(test[0], test[1].charAt(0));
				} else {
					types.put(test[0], 'D');
				}
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public Path diffCommand() {
		return diffCommand;
	}

	public Path graphvizPath() {
		return graphvizPath;
	}

	public Path tmp() {
		return tmp;
	}

	public Path result() {
		return result;
	}

	public TObjectCharMap<String> types() {
		return types;
	}

	public boolean onMemory() {
		return onMemory;
	}

	public boolean skip() {
		return skip;
	}

	public int diffType() {
		return diffType;
	}
}
