package org.opengion.fukurou.model;

import java.io.File;
import java.util.Locale;
import org.opengion.fukurou.util.StringUtil;


/**
 * ファイル操作のファクトリークラス
 *
 * デフォルトはローカルのファイル操作を行うFileOperationクラスを生成します。
 * 利用プラグイン、バケット、パス等を指定する事でクラウドのオブジェクトストレージに対応した
 * クラスを生成します。
 *
 * @og.rev 5.10.8.0 (2019/02/01) 新規作成
 * @og.rev 5.10.9.0 (2019/03/01) 変更対応
 * @author oota
 * @since JDK7.0
 */
// public class FileOperationFactory {
public final class FileOperationFactory {					// 7.2.9.4 (2020/11/20) PMD:A class which only has private constructors should be final
	private static final int BUFFER_MIDDLE = 200;

	/**
	 * オブジェクトを作らせない為の、private コンストラクタ
	 *
	 * @og.rev 7.2.9.4 (2020/11/20) オブジェクトを作らせない為の、private コンストラクタ
	 */
	private FileOperationFactory() {}

	/**
	 * インスタンス生成
	 *
	 * 引数を元に、ファイル操作インスタンスを生成します。
	 * ローカルのファイル操作を行うFileOperationクラスを返します。
	 *
	 * @param path ファイルパス
	 * @return ファイル操作インスタンス
	 */
	public static FileOperation newStorageOperation(final String path) {
//		return newStorageOperation( (String)null, null, path.toString());
		return newStorageOperation( (String)null, null, path);
	}

	/**
	 * インスタンス生成
	 *
	 * 引数を元に、ファイル操作クラスを生成します。
	 * プラグインとバケットを指定する事で、plugin.cloud内のクラウド用のクラスを返します。
	 *
	 * ディレクトリとファイル名からパスを生成します。
	 *
	 * @param plugin 利用プラグイン
	 * @param buket バケット名
	 * @param dir ディレクトリ
	 * @param fileName ファイル名
	 * @return ファイル操作インスタンス
	 */
	public static FileOperation newStorageOperation(final String plugin, final String buket, final String dir, final String fileName) {
		final StringBuilder path = new StringBuilder(BUFFER_MIDDLE);
		path.append( dir );

		if(fileName != null) {
			path.append(File.separator).append(fileName);
		}

		return newStorageOperation(plugin, buket, path.toString());
	}

	/**
	 * インスタンス生成
	 *
	 * 引数を元に、ファイル操作クラスを生成します。
	 * プラグインとバケットを指定する事で、plugin.cloud内のクラウド用のクラスを返します。
	 * プラグインがnull、もしくはDEFAULTの場合は標準のFileOperation(ローカルファイル用)を返します。
	 *
	 * @param plugin 利用プラグイン
	 * @param buket バケット名
	 * @param path ファイルパス
	 * @return ファイル操作インスタンス
	 */
	public static FileOperation newStorageOperation(final String plugin, final String buket, final String path) {
		FileOperation rtn;
		String cloudTarget = null;

		final Object[] args = new Object[] { buket, path };

		// 対象のクラウドサービスを取得(大文字化)。
		// 未指定の場合は、ローカルディレクトリを利用。
		if ( plugin != null && plugin.length() > 0 ) {
			cloudTarget = plugin.toUpperCase( Locale.JAPAN );
		}

		try {
			final StringBuilder sb = new StringBuilder(BUFFER_MIDDLE);

			if (StringUtil.isNull(cloudTarget) || "DEFAULT".equals(cloudTarget)) {
				sb.append("org.opengion.fukurou.model.FileOperation");
			} else {
				sb.append("org.opengion.plugin.cloud.")
					.append("FileOperation_")
					.append(cloudTarget);
			}

			rtn = (FileOperation) Class.forName(sb.toString())
					.getConstructor(String.class, String.class)
					.newInstance(args);
//		} catch (Exception e) {
		} catch (final Throwable th) {
			// キャッチしたエラー情報をスロー
			throw new RuntimeException(th);
		}

		return rtn;
	}

	/**
	 * インスタンス生成
	 *
	 * 引数を元に、ファイル操作クラスを生成します。
	 * 与えたfileオブジェクトがFileOperationだった場合は、プラグインとバケットを取得して
	 * それに基づいたFileOperationを返します。
	 * 標準のFileの場合は、defaultのFileOperationを返します。
	 * 元がnullの場合はnullを返します。
	 *
	 * @og.rev 7.2.9.4 (2020/11/20) PMD:Avoid declaring a variable if it is unreferenced before a possible exit point.
	 *
	 * @param file コピー元
	 * @param dir 親パス(ディレクトリ)
	 * @param fileName 子パス
	 * @return 設定をコピーしたのFileOperation
	 */
	public static FileOperation newStorageOperation(final File file, final String dir, final String fileName) {
		if( file == null) { return null; }

		String plugin = null;
		String buket = null;

//		if( file == null) { return null; }		// PMD:Avoid declaring a variable if it is unreferenced before a possible exit point.

		// FileOperation型の場合にプラグインを判定する
		if( file instanceof FileOperation ) {
			plugin = ((FileOperation)file).getPlugin();
			buket = ((FileOperation)file).getBucket();
		}

		return newStorageOperation( plugin, buket, dir, fileName);
	}

	/**
	 * インスタンス生成。
	 *
	 * コピーするタイプで、子パスを与えないパターンです。
	 *
	 * @param file コピー元
	 * @param path パス
	 * @return 設定をコピーしたのFileOperation
	 */
	public static FileOperation newStorageOperation(final File file, final String path) {
		return newStorageOperation( file, path, null);
	}
}
