package jp.sf.amateras.rdiffbackup.util;

import javax.servlet.http.HttpServletRequest;

import jp.sf.amateras.rdiffbackup.entity.BackupDir;
import jp.sf.amateras.rdiffbackup.service.ConfigService;

import org.seasar.framework.container.SingletonS2Container;
import org.seasar.framework.util.StringUtil;
import org.seasar.struts.util.RequestUtil;

/**
 * ファイルやディレクトリのパスを操作するためのユーティリティです。
 *
 * @author Naoki Takezoe
 */
public class PathUtil {

	/**
	 * rootパラメータのセキュリティチェックを行います。
	 * <p>
	 * 引数で指定された文字列がnullの場合、もしくは設定ファイルで指定したバックアップディレクトリの
	 * パスのいずれとも一致しない場合は<code>IllegalArgumentException</code>をスローします。
	 *
	 *
	 * @param root チェックするパラメータ
	 * @throws IllegalArgumentException セキュリティチェックに引っかかった場合
	 */
	public static void checkRoot(String root){
		if(root == null){
			throw new IllegalArgumentException();
		}

		ConfigService configService = SingletonS2Container.getComponent(ConfigService.class);

		for(BackupDir backupDir: configService.getBackupDirList()){
			if(backupDir.directory.equals(root)){
				return;
			}
		}
		throw new IllegalArgumentException();
	}

	/**
	 * pathパラメータのセキュリティチェックを行います。
	 * <p>
	 * 引数で指定した文字列がnullでなく、なおかつ".."を含む場合は<code>IllegalArgumentException</code>をスローします。
	 *
	 * @param path チェックするパラメータ
	 * @throws IllegalArgumentException セキュリティチェックに引っかかった場合
	 */
	public static void checkPath(String path){
		if(path != null && path.indexOf("..") >= 0){
			throw new IllegalArgumentException();
		}
	}

	/**
	 * バックアップのルートディレクトリと、
	 * ファイルまたはディレクトリのバックアップディレクトリ内でのパスを結合して絶対パスを生成します。
	 *
	 * @param root バックアップのルートディレクトリ
	 * @param path ファイルまたはディレクトリのバックアップディレクトリ内でのパス
	 * @return ファイルまたはディレクトリの絶対パス
	 */
	public static String buildPath(String root, String path){
		String result = root;

		if(StringUtil.isNotEmpty(result)){
			if(!result.endsWith("/")){
				result = result + "/";
			}
		} else {
			result = "";
		}

		if(StringUtil.isNotEmpty(path)){
			if(path.startsWith("/")){
				path = path.substring(1);
			}
			result = result + path;
		}

		return result;
	}

	/**
	 * パスから親ディレクトリのパスを取得します。
	 *
	 * @param path パス
	 * @return 親ディレクトリのパス
	 */
	public static String getParentPath(String path){
		if(path.endsWith("/")){
			path = path.substring(0, path.length() - 1);
		}

		int index = path.lastIndexOf('/');

		if(index >= 0){
			return path.substring(0, index);
		}

		return "";
	}

	/**
	 * パスから末尾のファイル名もしくはディレクトリ名部分を取得します。
	 *
	 * @param path ファイルまたはディレクトリのパス
	 * @return ファイル名またはディレクトリ名
	 */
	public static String getFileName(String path){
		if(path.endsWith("/")){
			path = path.substring(0, path.length() - 1);
		}

		int index = path.lastIndexOf('/');
		if(index >= 0){
			return path.substring(index + 1);
		}
		return null;
	}

	/**
	 * ダウンロード用のファイル名を取得します。
	 * ブラウザの種類に応じて文字コードの変換を行います。
	 *
	 * @param fileName ファイル名
	 * @return 文字コード変換後のファイル名
	 */
	public static String getDownloadFileName(String fileName){
		try {
			HttpServletRequest request = RequestUtil.getRequest();

			String userAgent = request.getHeader("USER-AGENT");
			if(userAgent != null){
				if(userAgent.indexOf("MSIE") >= 0 && userAgent.indexOf("Opera") < 0){
					fileName = new String(fileName.getBytes("Windows-31J"), "ISO8859_1");
				} else {
					fileName = new String(fileName.getBytes("UTF-8"), "ISO8859_1");
				}
			}
			return fileName;

		} catch(Exception ex){
			throw new RuntimeException(ex);
		}
	}
}
