/*
 * Copyright 2013 gitblit.com.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gitblit.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sun.jna.Library;
import com.sun.jna.Native;

/**
 * Collection of static methods to access native OS library functionality.
 *
 * @author Florian Zschocke
 */
public class JnaUtils {
	public static final int S_ISUID =  0004000; // set user id on execution
	public static final int S_ISGID =  0002000; // set group id on execution
	public static final int S_ISVTX =  0001000; // sticky bit, save swapped text even after use

	public static final int S_IRWXU =  0000700; // RWX mask for owner
	public static final int S_IRUSR =  0000400; // read permission for owner
	public static final int S_IWUSR =  0000200; // write permission for owner
	public static final int S_IXUSR =  0000100; // execute/search permission for owner
	public static final int S_IRWXG =  0000070; // RWX mask for group
	public static final int S_IRGRP =  0000040; // read permission for group
	public static final int S_IWGRP =  0000020; // write permission for group
	public static final int S_IXGRP =  0000010; // execute/search permission for group
	public static final int S_IRWXO =  0000007; // RWX mask for other
	public static final int S_IROTH =  0000004; // read permission for other
	public static final int S_IWOTH =  0000002; // write permission for other
	public static final int S_IXOTH =  0000001; // execute/search permission for other

	public static final int S_IFMT =   0170000; // type of file mask
	public static final int S_IFIFO =  0010000; // named pipe (fifo)
	public static final int S_IFCHR =  0020000; // character special device
	public static final int S_IFDIR =  0040000; // directory
	public static final int S_IFBLK =  0060000; // block special device
	public static final int S_IFREG =  0100000; // regular file
	public static final int S_IFLNK =  0120000; // symbolic link
	public static final int S_IFSOCK = 0140000; // socket


	private static final Logger LOGGER = LoggerFactory.getLogger(JGitUtils.class);

	private static UnixCLibrary unixlibc = null;


	/**
	 * Utility method to check if the JVM is running on a Windows OS.
	 *
	 * @return true, if the system property 'os.name' starts with 'Windows'.
	 */
	public static boolean isWindows()
	{
		return System.getProperty("os.name").toLowerCase().startsWith("windows");
	}


	private interface UnixCLibrary extends Library {
		public int chmod(String path, int mode);
		public int getgid();
		public int getegid();
	}


	public static int getgid()
	{
		if (isWindows()) {
			throw new UnsupportedOperationException("The method JnaUtils.getgid is not supported under Windows.");
		}

		return getUnixCLibrary().getgid();
	}


	public static int getegid()
	{
		if (isWindows()) {
			throw new UnsupportedOperationException("The method JnaUtils.getegid is not supported under Windows.");
		}

		return getUnixCLibrary().getegid();
	}


	/**
	 * Set the permission bits of a file.
	 *
	 * The permission bits are set to the provided mode. This method is only
	 * implemented for OSes of the Unix family and makes use of the 'chmod'
	 * function of the native C library. See 'man 2 chmod' for more information.
	 *
	 * @param path
	 * 			File/directory to set the permission bits for.
	 * @param mode
	 * 			A mode created from or'd permission bit masks S_I*
	 * @return	Upon successful completion, a value of 0 returned. Otherwise, a value of -1 is returned.
	 */
	public static int setFilemode(File file, int mode)
	{
		return setFilemode(file.getAbsolutePath(), mode);
	}

	/**
	 * Set the permission bits of a file.
	 *
	 * The permission bits are set to the provided mode. This method is only
	 * implemented for OSes of the Unix family and makes use of the 'chmod'
	 * function of the native C library. See 'man 2 chmod' for more information.
	 *
	 * @param path
	 * 			Path to a file/directory to set the permission bits for.
	 * @param mode
	 * 			A mode created from or'd permission bit masks S_I*
	 * @return	Upon successful completion, a value of 0 returned. Otherwise, a value of -1 is returned.
	 */
	public static int setFilemode(String path, int mode)
	{
		if (isWindows()) {
			throw new UnsupportedOperationException("The method JnaUtils.getFilemode is not supported under Windows.");
		}

		return getUnixCLibrary().chmod(path, mode);
	}



	/**
	 * Get the file mode bits of a file.
	 *
	 * This method is only implemented for OSes of the Unix family. It returns the file mode
	 * information as available in the st_mode member of the resulting struct stat when calling
	 * 'lstat' on a file.
	 *
	 * @param path
	 * 			File/directory to get the file mode from.
	 * @return	Upon successful completion, the file mode bits are returned. Otherwise, a value of -1 is returned.
	 */
	public static int getFilemode(File path)
	{
		return getFilemode(path.getAbsolutePath());
	}

	/**
	 * Get the file mode bits of a file.
	 *
	 * This method is only implemented for OSes of the Unix family. It returns the file mode
	 * information as available in the st_mode member of the resulting struct stat when calling
	 * 'lstat' on a file.
	 *
	 * @param path
	 * 			Path to a file/directory to get the file mode from.
	 * @return	Upon successful completion, the file mode bits are returned. Otherwise, a value of -1 is returned.
	 */
	public static int getFilemode(String path)
	{
		if (isWindows()) {
			throw new UnsupportedOperationException("The method JnaUtils.getFilemode is not supported under Windows.");
		}

		Filestat stat = getFilestat(path);
		if ( stat == null ) return -1;
		return stat.mode;
	}


	/**
	 * Status information of a file.
	 */
	public static class Filestat
	{
		public int mode;  // file mode, permissions, type
		public int uid;   // user Id of owner
		public int gid;   // group Id of owner

		Filestat(int mode, int uid, int gid) {
			this.mode = mode; this.uid = uid; this.gid = gid;
		}
	}


	/**
	 * Get Unix file status information for a file.
	 *
	 * This method is only implemented for OSes of the Unix family. It returns file status
	 * information for a file. Currently this is the file mode, the user id and group id of the owner.
	 *
	 * @param path
	 * 			File/directory to get the file status from.
	 * @return	Upon successful completion, a Filestat object containing the file information is returned.
	 * 			Otherwise, null is returned.
	 */
	public static Filestat getFilestat(File path)
	{
		return getFilestat(path.getAbsolutePath());
	}


	/**
	 * Get Unix file status information for a file.
	 *
	 * This method is only implemented for OSes of the Unix family. It returns file status
	 * information for a file. Currently this is the file mode, the user id and group id of the owner.
	 *
	 * @param path
	 * 			Path to a file/directory to get the file status from.
	 * @return	Upon successful completion, a Filestat object containing the file information is returned.
	 * 			Otherwise, null is returned.
	 */
	public static Filestat getFilestat(String path)
	{
		if (isWindows()) {
			throw new UnsupportedOperationException("The method JnaUtils.getFilestat is not supported under Windows.");
		}


		int mode = 0;

		// Use a Runtime, because implementing stat() via JNA is just too much trouble.
		// This could be done with the 'stat' command, too. But that may have a shell specific implementation, so we use 'ls' instead.
		String lsLine = runProcessLs(path);
		if (lsLine == null) {
			LOGGER.debug("Could not get file information for path " + path);
			return null;
		}

		Pattern p = Pattern.compile("^(([-bcdlspCDMnP?])([-r][-w][-xSs])([-r][-w][-xSs])([-r][-w][-xTt]))[@+.]? +[0-9]+ +([0-9]+) +([0-9]+) ");
		Matcher m = p.matcher(lsLine);
		if ( !m.lookingAt() ) {
			LOGGER.debug("Could not parse valid file mode information for path " + path);
			return null;
		}

		// Parse mode string to mode bits
		String group = m.group(2);
		switch (group.charAt(0)) {
		case 'p' :
			mode |= 0010000; break;
		case 'c':
			mode |= 0020000; break;
		case 'd':
			mode |= 0040000; break;
		case 'b':
			mode |= 0060000; break;
		case '-':
			mode |= 0100000; break;
		case 'l':
			mode |= 0120000; break;
		case 's':
			mode |= 0140000; break;
		}

		for ( int i = 0; i < 3; i++) {
			group = m.group(3 + i);
			switch (group.charAt(0)) {
			case 'r':
				mode |= (0400 >> i*3); break;
			case '-':
				break;
			}

			switch (group.charAt(1)) {
			case 'w':
				mode |= (0200 >> i*3); break;
			case '-':
				break;
			}

			switch (group.charAt(2)) {
			case 'x':
				mode |= (0100 >> i*3); break;
			case 'S':
				mode |= (04000 >> i); break;
			case 's':
				mode |= (0100 >> i*3);
				mode |= (04000 >> i); break;
			case 'T':
				mode |= 01000; break;
			case 't':
				mode |= (0100 >> i*3);
				mode |= 01000; break;
			case '-':
				break;
			}
		}

		return new Filestat(mode, Integer.parseInt(m.group(6)), Integer.parseInt(m.group(7)));
	}


	/**
	 * Run the unix command 'ls -ldn' on a single file and return the resulting output line.
	 *
	 * @param path
	 * 			Path to a single file or directory.
	 * @return The first line of output from the 'ls' command. Null, if an error occurred and no line could be read.
	 */
	private static String runProcessLs(String path)
	{
		String cmd = "ls -ldn " + path;
		Runtime rt = Runtime.getRuntime();
		Process pr = null;
		InputStreamReader ir = null;
		BufferedReader br = null;
		String output = null;

		try {
			pr = rt.exec(cmd);
			ir = new InputStreamReader(pr.getInputStream());
			br = new BufferedReader(ir);

			output = br.readLine();

			while (br.readLine() != null) ; // Swallow remaining output
		}
		catch (IOException e) {
			LOGGER.debug("Exception while running unix command '" + cmd + "': " + e);
		}
		finally {
			if (pr != null) try { pr.waitFor();	} catch (Exception ignored) {}

			if (br != null) try { br.close(); } catch (Exception ignored) {}
			if (ir != null) try { ir.close(); } catch (Exception ignored) {}

			if (pr != null) try { pr.getOutputStream().close();	} catch (Exception ignored) {}
			if (pr != null) try { pr.getInputStream().close();	} catch (Exception ignored) {}
			if (pr != null) try { pr.getErrorStream().close();	} catch (Exception ignored) {}
		}

		return output;
	}


	private static UnixCLibrary getUnixCLibrary()
	{
		if (unixlibc == null) {
			unixlibc = (UnixCLibrary) Native.loadLibrary("c", UnixCLibrary.class);
			if (unixlibc == null) throw new RuntimeException("Could not initialize native C library.");
		}
		return unixlibc;
	}

}
