/* Copyright (c) 2013 Alexander Sherstnev
 *  
 *  JAva Bioinformatics Analysis Web Services (JABAWS) @version: 2.0     
 * 
 *  This library is free software; you can redistribute it and/or modify it under the terms of the
 *  Apache License version 2 as published by the Apache Software Foundation
 * 
 *  This library 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 Apache 
 *  License for more details.
 * 
 *  A copy of the license is in apache_license.txt. It is also available here:
 * @see: http://www.apache.org/licenses/LICENSE-2.0.txt
 * 
 * Any republication or derived work distributed in source code form
 * must include this copyright and license notice.
 */
package compbio.stat.collector;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;

import compbio.engine.client.Executable;
import compbio.engine.client.SkeletalExecutable;
import compbio.metadata.JobStatus;
import compbio.util.FileUtil;
import compbio.ws.client.Services;
import compbio.ws.client.ServicesUtil;

/**
 * 
 * @author Alexander Sherstnev
 * 
 */
public class JobDirectory {

	static final int UNDEFINED = -1;

	private static final Logger log = Logger.getLogger(JobDirectory.class);
	
	File jobdir;
	Map<String, File> files = new HashMap<String, File>();

	JobDirectory(File directory) {
		this.jobdir = directory;
		for (File f : jobdir.listFiles()) {
		files.put(f.getName(), f);
		}
	}

	boolean hasStatus(JobStatus status) {
		return files.containsKey(status.toString());
	}

	boolean isCollected() {
		return hasStatus(JobStatus.COLLECTED);
	}

	boolean isCancelled() {
		return hasStatus(JobStatus.CANCELLED);
	}

	long getStartTime() {
		long starttime = UNDEFINED;
		File startfile = files.get(JobStatus.STARTED.toString());
		if (startfile == null) {
			startfile = files.get(JobStatus.SUBMITTED.toString());
		}
		try {
			if (startfile != null) {
				String start = FileUtil.readFileToString(startfile);
				starttime = Long.parseLong(start.trim());
			}
		} catch (IOException ignore) {
			log.warn("IOException while reading STARTED status file! Ignoring...", ignore);
			// fall back
			starttime = startfile.lastModified();
		} catch (NumberFormatException ignore) {
			log.warn("NumberFormatException while reading STARTED status file! Ignoring...", ignore);
			// fall back
			starttime = startfile.lastModified();
		}
		return starttime;
	}

	String getClusterJobID() {
		String clustjobId = "";
		File jobid = files.get("JOBID");
		try {
		if (jobid != null) {
			clustjobId = FileUtil.readFileToString(jobid);
		}
		} catch (IOException ioe) {
		log.error(
			"IO Exception while reading the content of JOBID file for job "
				+ jobid, ioe);
		}
		return clustjobId.trim();
	}

	long getFinishedTime() {
		long ftime = UNDEFINED;
		File finished = files.get(JobStatus.FINISHED.toString());
		if (finished != null) {
		try {
			if (finished != null) {
			String start = FileUtil.readFileToString(finished);
			ftime = Long.parseLong(start.trim());
			}
		} catch (IOException ignore) {
			log.warn(
				"IOException while reading FINISHED status file! Ignoring...",
				ignore);
			// fall back
			ftime = finished.lastModified();
		} catch (NumberFormatException ignore) {
			log.warn(
				"NumberFormatException while reading FINISHED status file! Ignoring...",
				ignore);
			// fall back
			ftime = finished.lastModified();
		}
		}
		return ftime;
	}

	private Services getService() {
		return ServicesUtil.getServiceByJobDirectory(jobdir);
	}

	long getResultSize() {
		Class<? extends Executable<?>> name = ServicesUtil
			.getRunnerByJobDirectory(jobdir);

		File f = null;
		if (name.getSimpleName().equalsIgnoreCase("IUPred")) {
		f = files.get("out.glob");
		if (f == null)
			f = files.get("out.short");
		if (f == null)
			f = files.get("out.long");
		} else {
		f = files.get(SkeletalExecutable.OUTPUT);
		}
		if (f != null) {
		return f.length();
		}
		return UNDEFINED;
	}

	long getInputSize() {
		Class<? extends Executable<?>> name = ServicesUtil
			.getRunnerByJobDirectory(jobdir);

		File input = files.get(SkeletalExecutable.INPUT);
		if (input != null) {
		return input.length();
		}
		return UNDEFINED;
	}

	JobStat getJobStat() {
		return JobStat.newInstance(getService(), getClusterJobID(),
			jobdir.getName(), getStartTime(), getFinishedTime(),
			getInputSize(), getResultSize(), isCancelled(),
			isCollected());
	}

	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
			+ ((jobdir == null) ? 0 : jobdir.hashCode());
		return result;
	}

	public boolean equals(Object obj) {
		if (this == obj)
		return true;
		if (obj == null)
		return false;
		if (getClass() != obj.getClass())
		return false;
		JobDirectory other = (JobDirectory) obj;
		if (jobdir == null) {
		if (other.jobdir != null)
			return false;
		} else if (!jobdir.equals(other.jobdir))
		return false;
		return true;
	}
}

