package routines;

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Date;

import org.apache.commons.io.FilenameUtils;

/*
 * user specification: the function's comment should contain keys as follows: 1. write about the function's comment.but
 * it must be before the "{talendTypes}" key.
 * 
 * 2. {talendTypes} 's value must be talend Type, it is required . its value should be one of: String, char | Character,
 * long | Long, int | Integer, boolean | Boolean, byte | Byte, Date, double | Double, float | Float, Object, short |
 * Short
 * 
 * 3. {Category} define a category for the Function. it is required. its value is user-defined .
 * 
 * 4. {param} 's format is: {param} <type>[(<default value or closed list values>)] <name>[ : <comment>]
 * 
 * <type> 's value should be one of: string, int, list, double, object, boolean, long, char, date. <name>'s value is the
 * Function's parameter name. the {param} is optional. so if you the Function without the parameters. the {param} don't
 * added. you can have many parameters for the Function.
 * 
 * 5. {example} gives a example for the Function. it is optional.
 */
public class LcagFileTools
{

    
	private static LcagLogger log = LcagLogger.getLogger(LcagFileTools.class);
	
    /**
     * getName: Get only the name of the given file path (name with extension)  
     *
     * {talendTypes} String
     *
     * {Category} LCAG-File
     *
     * {param} string filePath: File path to use
     *
     * {example} getName("a/b/HelloWorld.txt") = "HelloWorld.txt"
     */
	public static String getName(String filePath) {
		String result = FilenameUtils.getName(filePath);

		return result;
	}

    /**
     * getBaseName: Get the base name of the given file path (without extension)  
     *
     * {talendTypes} String
     *
     * {Category} LCAG-File
     *
     * {param} string filePath: File path to use
     *
     * {example} getName("a/b/HelloWorld.txt") = "HelloWorld"
     */
	public static String getBaseName(String filePath) {
		String result = FilenameUtils.getBaseName(filePath);

		return result;
	}

    /**
     * getBaseName: Get the extension of the given file path.  
     *
     * {talendTypes} String
     *
     * {Category} LCAG-File
     *
     * {param} string filePath: File path to use
     *
     * {example} getName("a/b/HelloWorld.txt") = "txt"
     */
	public static String getExtension(String filePath) {
		String result = FilenameUtils.getExtension(filePath);

		return result;
	}

    /**
     * getBaseName: Get the path of the given file path without the file name.  
     *
     * {talendTypes} String
     *
     * {Category} LCAG-File
     *
     * {param} string filePath: File path to use
     *
     * {example} getName("a/b/HelloWorld.txt") = "a/b";
     */
	public static String getPath(String filePath) {
		String result = FilenameUtils.getPath(filePath);

		return result;
	}

	/**
     * readTextFile: Read a file as String 
     *
     *
     * {talendTypes} String
     *
     * {Category} LCAG-File
     *
     * {param} string fileName: File to read
     *
     * {example} readTextFile("HelloWorld.txt")
     */
	public static String readTextFile(String fileName) throws java.io.IOException {
		String result = null;
		File file = new File(fileName);
		String fPath = file.getAbsolutePath();
		
		java.nio.file.Path filePath = java.nio.file.Paths.get(fPath);

		byte[] fileContent = java.nio.file.Files.readAllBytes(filePath);
		
		result	= new String(fileContent);

		return result;
	}

	/**
     * createSameJobFileName: For a context.env_inputDirectory/fileName.ext create a new file name 
     * for the same job. The target in relative (see rePath) to the input directory: {targetDir}/fileName{preExtension}.ext
     * 
     * {talendTypes} String
     * 
     * {Category} LCAG
     * 
     * {param} String("srcFileName") input: source file name
     * {param} String("targetDir")    input: Target directory. use context.env_outputDir, context.env_tempDir, ...
     * {param} String("preExtension") input: file name part to prepend before the file name extension
     * {param} String("ext") 		  input: use this extension instead of original one
     * 
     * 
     */    
    public static String createSameJobFileName(String srcFileName, String targetDir, String preExtension, String ext)
    {
    	if (srcFileName == null)	return null;
    	if (preExtension == null)	preExtension = "";
    	if (ext == null)			ext = FilenameUtils.getExtension(srcFileName);
    	
    	// get basename without extension
    	String baseName = FilenameUtils.getBaseName(srcFileName);
    	
    	String result = String.format("%s/%s%s.%s", targetDir, baseName, preExtension, ext);
    	result = FilenameUtils.normalize(result);

    	return result;
    }	
	

	/**
     * createSameJobFileName: For a context.env_inputDirectory/fileName.ext create a new file name 
     * for the same job. The target in relative (see rePath) to the input directory: {targetDir}/fileName{preExtension}.ext
     * 
     * {talendTypes} String
     * 
     * {Category} LCAG
     * 
     * {param} String("srcFileName") input: source file name
     * {param} String("targetDir")    input: Target directory. use context.env_outputDir, context.env_tempDir, ...
     * {param} String("preExtension") input: file name part to prepend before the file name extension
     * 
     * 
     */    
    public static String createSameJobFileName(String srcFileName, String targetDir, String preExtension)
    {
    	if (srcFileName == null)	return null;
    	
    	String ext = FilenameUtils.getExtension(srcFileName);
    	
    	String result = createSameJobFileName(srcFileName, targetDir, preExtension, ext);

    	return result;
    }	

    /**
     * createJobFileName: For a context.env_inputDirectory/fileName.ext create a new file name 
     * as  context.env_inputDirectory/../{jobName}/fileName{preExtension}.ext
     * 
     * 
     * {talendTypes} String
     * 
     * {Category} LCAG
     * 
     * {param} String("srcFileName") input: source file name
     * {param} String("jobName")      input: usually the 'jobName' variable in Talend Jobs
     * {param} String("preExtension") input: file name part to prepend before the file name extension
     * 
     * 
     */    
    public static String createJobFileName(String srcFileName, String jobName, String preExtension)
    {
    	if (srcFileName == null)	return null;
    	if (jobName == null)		return srcFileName;
    	if (preExtension == null)	preExtension = "";
    	
    	File theFile = new File(srcFileName);
    	String dirName = theFile.getParent();
    	String baseName = FilenameUtils.getBaseName(srcFileName);
    	String ext = FilenameUtils.getExtension(srcFileName);
    	
    	String result = String.format("%s/../%s/%s%s.%s", dirName, jobName, baseName, preExtension, ext);
    	result = FilenameUtils.normalize(result);
    	return result;
    }	

	/**
     * createJobTempFileName: For a context.env_inputDirectory/fileName.ext create a new file name 
     * for the same jobs temp directory as context.env_inputDirectory/../{jobName}/fileName{preExtension}.ext
     * 
     * 
     * {talendTypes} String
     * 
     * {Category} LCAG
     * 
     * {param} String("srcFileName") input: source file name
     * {param} String("jobName")      input: usually the 'jobName' variable in Talend Jobs
     * {param} String("preExtension") input: file name part to prepend before the file name extension
     * {param} String("ext") 		  input: use thzis extension instead of original one
     * 
     * 
     */    
    public static String createJobTempFileName(String srcFileName, String preExtension, String ext)
    {
    	String result = createSameJobFileName(srcFileName, "../../../temp", preExtension, ext);

    	return result;
    }	

    /**
     * createInputDirFileName4OtherJob: For a context.env_inputDirectory/fileName.ext or context.env_inputDirectory/fileName.ext
     * create a new file name for the input directory of the other given jobname as fileName{preExtension}.ext
     *  
     * {talendTypes} String
     * 
     * {Category} LCAG-File
     * 
     * {param} String("srcFileName") input: source file name
     * {param} String("jobName")      input: usually the 'jobName' variable in Talend Jobs
     * {param} String("preExtension") input: file name part to prepend before the file name extension
     * 
     * 
     */    
    public static String createInputDirFileName4OtherJob(String srcFileName, String jobName, String preExtension)
    {
    	if (srcFileName == null) throw new IllegalArgumentException("File name argument must not be null");
    	
    	if (jobName == null)		return srcFileName;
    	if (preExtension == null)	preExtension = "";
    	
    	Path absPath = Paths.get(srcFileName).toAbsolutePath();
    	Path thisJobDir = absPath.getParent();
    	Path thisJobDirParent = thisJobDir.getParent();
    	String otherJobInputDir = null;
    	
    	if (thisJobDirParent.endsWith("input")) {
    		otherJobInputDir = thisJobDirParent.toString();
    	} else if (thisJobDirParent.endsWith("temp")) {
    		otherJobInputDir = thisJobDirParent.getParent() + "/data/input/";
    	} else {
    		throw new UnsupportedOperationException("Source file name argument must be in env_inputDirectory or env_temDirectory");
    	}
    	
    	String baseName = FilenameUtils.getBaseName(srcFileName);
    	String ext = FilenameUtils.getExtension(srcFileName);
    	String result = String.format("%s/%s/%s%s.%s", otherJobInputDir, jobName, baseName, preExtension, ext);
    	Path resultPath = Paths.get(result);
    	
    	result = resultPath.normalize().toString().replace("\\",  "/");
    	return result;
    }	

    /**
     * createJobTempFileName: For a context.env_inputDirectory/fileName.ext create a new file name 
     * for the same jobs temp directory as context.env_inputDirectory/../{jobName}/fileName{preExtension}
     * 
     * 
     * {talendTypes} String
     * 
     * {Category} LCAG
     * 
     * {param} String("srcFileName") input: source file name
     * {param} String("preExtension") input: file name part to prepend before the file name extension
     * 
     * 
     */    

    public static String createJobTempFileName(String srcFileName, String preExtension)
    {
    	if (srcFileName == null)	return null;
    	if (preExtension == null)	preExtension = "";
    	
    	File theFile = new File(srcFileName);
    	String dirName = theFile.getParent();
    	String jobName = FilenameUtils.getBaseName(dirName);
    	String baseName = FilenameUtils.getBaseName(srcFileName);
    	String ext = FilenameUtils.getExtension(srcFileName);
    	
    	String result = String.format("%s/../../../temp/%s/%s%s.%s", dirName, jobName, baseName, preExtension, ext);
    	result = FilenameUtils.normalize(result);

    	return result;
    }	
	
      /**
     * createTimestampedFileName: Used for receive jobs and export from DB Jobs, only.
     * 
     * Creates a file name starting with a UTC timestamp for a given date. Drops
     * leading directory path.
     *       
     * {talendTypes} String
     * 
     * {Category} LCAG-File
     * 
     * {param} String("aDate") input: Date to use for timestamp 
     * {param} String("srcFileName") input: source file name
     * 
     * 
     */    
    public static String createTimestampedFileName(Date aDate, String srcFileName)
    {
    	if ( aDate == null) {
    		aDate = TalendDate.getCurrentDate();
    	}
		String srcFileBaseName = FilenameUtils.getName((String)srcFileName);
    	String tsString = TalendDate.formatDateInUTC(LcagDateTime.MDM_FILE_TIMESTAMP_FORMAT_STR, aDate);
  	
    	String result = String.format("%s_%s", tsString, srcFileBaseName);

    	return result;
    }	
	
    /**
     * createTimestampedFileName: Used for receive jobs and export from DB Jobs, only.
     * 
     * Creates a file name starting with a current UTC timestamp.
     *       
     * {talendTypes} String
     * 
     * {Category} LCAG
     * 
     * {param} String("srcFileName") input: source file name
     * 
     * 
     */    
    public static String createTimestampedFileName(String srcFileName)
    {
    	
    	String result = createTimestampedFileName(TalendDate.getCurrentDate(), srcFileName);

    	return result;
    }	

	/**
     * getFileTimestampAsString: retrieves the MDM timestamp prefix of a given file name.
     * 
     * {talendTypes} Object 
     * 
     * {Category} LCAG
     * 
     * {param} String("srcFileName") input: file name with timestamp prefix
     * 
     * 
     */    
    public static String getFileTimestampAsString(Object srcFileName) {
    	String result = null;
    	
		String srcFileBaseName = FilenameUtils.getBaseName((String)srcFileName);
		
		result = srcFileBaseName.substring(0, LcagConstant.FILE_TIMESTAMP_FORMAT.length());
    	return result;
    }
    
	/**
     * getFileTimestamp: retrieves the MDM data denoted by the MDM timestamp prefix of a given file name.
     * 
     * {talendTypes} Date
     * 
     * {Category} LCAG
     * 
     * {param} String("srcFileName") input: file name with timestamp prefix
     * 
     * 
     */    
    public static Date getFileTimestamp(String srcFileName)
    {
		Date 	timestamp = null;
    	int    	len = (srcFileName == null) ? 0 : srcFileName.length();
    	
    	if (len > 0) {
    		String timestampString = getFileTimestampAsString(srcFileName);
    		timestamp = LcagDateTime.secureParseDate(LcagConstant.FILE_TIMESTAMP_FORMAT, timestampString);
    	}
    	
    	return timestamp;
    }	
    
    /**
     * createPrefixedFileName: Used for jobs, only.
     * 
     * Creates a file name starting with a current UTC timestamp and a number. Create for receiving multiple messages:
     * The file name should start with the context.env_jobTimestamp followed by a number n that defines the n-th message received
     * 
     * Note: The prefix should identify the data flow of an incoming message throughout its entire processing by multiple jobs
     *       
     * {talendTypes} String
     * 
     * {Category} LCAG-File
     * 
     * {param} String("srcFileName") input: source file name
     * {param} Date("d") 		     input: Date to use, recommended: context.env_jobTimestamp
     * {param} int("n") 		     input: Number to make the prefix unique throughout all jobs 
     * 
     * 
     */    
    public static String createPrefixedFileName(String srcFileName, Date d, int n)
    {
    	String prefix = LcagDateTime.MDM_FILE_TIMESTAMP_FORMAT.format(d) + String.format("-x%05d_", n);
    	String result = prefix + srcFileName;

    	return result;
    }	

    /**
     * getFileNamePrefix: Used to fetch the file name prefix created by function createPrefixedFileName. 
     * This prefix should identify the data flow of an incoming message throughout its entire processing by multiple jobs
     * 
     * Note: This version supports the new prefix type (Timestamp prefix with number) as well as the old format (only Timestamp) 
     * 
     * {talendTypes} String
     * 
     * {Category} LCAG-File
     * 
     * {param} String("srcFileName") input: source file name
     */    
    public static String getFileNamePrefix(String srcFileName)
    {
    	String result = "";
    	
    	if (srcFileName == null) throw new IllegalArgumentException("File name argument must not be null");
    	
		String srcFileBaseName = FilenameUtils.getBaseName((String)srcFileName);
		
		if (srcFileBaseName.indexOf("-x") < 0) {
			result = getFileTimestampAsString(srcFileName);
			
			if (result == null) result = ""; 
		} else {
			// replace needed to correctly handle formats including 'T' or 'Z': 
			int prefixLength = LcagDateTime.MDM_FILE_TIMESTAMP_FORMAT_STR.replace("'", "").length() + String.format("-x%05d_", 0).length();
		
			if (srcFileBaseName.length() >= prefixLength) {
				result = srcFileBaseName.substring(0, prefixLength);			
			}
		}
		
    	return result;
    }	
}
