/*
 * Copyright (c) 2009 The openGion Project.
 *
 * 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 org.opengion.hayabusa.io;

import java.io.File;
import java.util.function.Supplier;									// 8.0.0.2 (2021/10/15)

import org.opengion.fukurou.model.FileOperation;
import org.opengion.fukurou.model.FileOperationFactory;
import org.opengion.fukurou.util.StringUtil;
import org.opengion.fukurou.util.FileUtil;							// 8.0.0.2 (2021/10/15)
import org.opengion.hayabusa.common.HybsSystem;
// import org.opengion.fukurou.system.HybsConst;					// 5.10.9.0 (2019/03/01)

/**
 * ｸﾗｳﾄﾞを含むﾌｧｲﾙ操作ｸﾗｽの生成
 *
 * ｼｽﾃﾑﾘｿｰｽ参照のみで､ｸﾗｳﾄﾞｸﾗｽを生成します｡(8.0.0.1 (2021/10/08)で固定)
 * 引数付きの場合は､直接､org.opengion.fukurou.model.FileOperationFactory をご利用ください｡
 *
 * 直接fukurouをCallしてもよいのですが､hayabusaからの呼び出しではｼｽﾃﾑﾘｿｰｽを参照する必要があるため
 * ﾗｯﾊﾟｰ的にこのｸﾗｽを経由してCallする事でｼｽﾃﾑﾘｿｰｽが使われるようにしておきます｡
 * （ﾀｸﾞ以外からも呼び出されるため､commonTagSupportではなく専用ｸﾗｽをioﾊﾟｯｹｰｼﾞに作成しています）
 *
 * ※ plugin → storage に変更｡
 *
 * ﾛｰｶﾙのﾌｧｲﾙを扱いたい場合は､storageかbucketにLOCALを指定してください｡
 *
 * @og.rev 5.10.8.0 (2019/02/01) 新規作成
 * @og.rev 8.0.0.1 (2021/10/08) 修正対応
 * @og.group
 *
 * @version 5.0
 * @author Takahashi Masakazu
 * @since JDK7.0
 */
public final class HybsFileOperationFactory {
	private static String STORAGE = HybsSystem.sys("CLOUD_TARGET");
	private static String BUCKET  = HybsSystem.sys("CLOUD_BUCKET");

	/**
	 * ｺﾝｽﾄﾗｸﾀはprivate化しておきます｡
	 */
	private HybsFileOperationFactory(){
		// ｺﾝｽﾄﾗｸﾀ
	}

	/**
	 * fukurouのFileOperationFactoryを呼び出してFileOperationを取得します｡
	 * storage,bucketを指定しない場合はｼｽﾃﾑﾘｿｰｽを利用します｡
	 *
	 * @og.rev 8.0.1.0 (2021/10/29) useLocal 属性を追加
	 *
	 * @param useLocal 強制的にﾛｰｶﾙﾌｧｲﾙを使用する場合､true にｾｯﾄします｡
	 * @param path ﾌｧｲﾙﾊﾟｽ
	 * @return FileOperationｲﾝｽﾀﾝｽ
	 */
	public static FileOperation create( final boolean useLocal,final String path ) {
		final String bucket = useLocal ? FileOperation.LOCAL : BUCKET ;

		return FileOperationFactory.newStorageOperation( STORAGE,bucket,path );
	}

	/**
	 * ﾃﾞｨﾚｸﾄﾘとﾌｧｲﾙ名を指定用です｡
	 *
	 * @og.rev 8.0.1.0 (2021/10/29) useLocal 属性を追加
	 *
	 * @param useLocal 強制的にﾛｰｶﾙﾌｧｲﾙを使用する場合､true にｾｯﾄします｡
	 * @param dir ﾃﾞｨﾚｸﾄﾘﾊﾟｽ
	 * @param fileName ﾌｧｲﾙ名
	 * @return FileOperationｲﾝｽﾀﾝｽ
	 */
	public static FileOperation create( final boolean useLocal,final String dir, final String fileName ) {
		final String bucket = useLocal ? FileOperation.LOCAL : BUCKET ;
		return FileOperationFactory.newStorageOperation( STORAGE,bucket,dir,fileName );		// 連結方法を統一します｡
	}

	/**
	 * FileOperation(ﾃﾞｨﾚｸﾄﾘ)とﾌｧｲﾙ名を指定用です｡
	 *
	 * @og.rev 8.0.1.0 (2021/10/29) useLocal 属性を追加
	 *
	 * @param useLocal 強制的にﾛｰｶﾙﾌｧｲﾙを使用する場合､true にｾｯﾄします｡
	 * @param dir ﾌｧｲﾙ(ﾃﾞｨﾚｸﾄﾘﾊﾟｽ取得)
	 * @param fileName ﾌｧｲﾙ名
	 * @return FileOperationｲﾝｽﾀﾝｽ
	 */
	public static FileOperation create( final boolean useLocal,final File dir, final String fileName ) {
		return create( useLocal,new File( dir,fileName ).getPath() );
	}

//	/**
//	 * fukurouのFileOperationFactoryを呼び出してFileOperationを取得します｡
//	 * storage,bucketを指定しない場合はｼｽﾃﾑﾘｿｰｽを利用します｡
//	 *
//	 * @param storage ｽﾄﾚｰｼﾞ(AWS など)
//	 * @param bucket ﾊﾞｹｯﾄ名
//	 * @param path ﾌｧｲﾙﾊﾟｽ
//	 * @return FileOperationｲﾝｽﾀﾝｽ
//	 */
//	public static FileOperation create(final String storage, final String bucket, final String path) {
//		return FileOperationFactory.newStorageOperation(
//				StringUtil.nval(storage, STORAGE), StringUtil.nval(bucket, BUCKET), path );
//	}

//	/**
//	 * FileOperation(ﾃﾞｨﾚｸﾄﾘ)とﾌｧｲﾙ名を指定用です｡
//	 *
//	 * @param storage ｽﾄﾚｰｼﾞ(AWS など)
//	 * @param bucket ﾊﾞｹｯﾄ名
//	 * @param dir ﾌｧｲﾙ(ﾃﾞｨﾚｸﾄﾘﾊﾟｽ取得)
//	 * @param filename ﾌｧｲﾙ名
//	 * @return FileOperationｲﾝｽﾀﾝｽ
//	 */
//	public static FileOperation create(final String storage, final String bucket, final File dir, final String filename) {
//		return create(storage, bucket, new File( dir,filename ).getPath() );
//	}

//	/**
//	 * ﾃﾞｨﾚｸﾄﾘとﾌｧｲﾙ名を指定用です｡
//	 *
//	 * @param storage ｽﾄﾚｰｼﾞ(AWS など)
//	 * @param bucket ﾊﾞｹｯﾄ名
//	 * @param dir ﾃﾞｨﾚｸﾄﾘﾊﾟｽ
//	 * @param filename ﾌｧｲﾙ名
//	 * @return FileOperationｲﾝｽﾀﾝｽ
//	 */
//	public static FileOperation create(final String storage, final String bucket, final String dir, final String filename) {
//		return create(storage, bucket, new File( dir,filename ).getPath() );
//	}

	/**
	 * ｼｽﾃﾑ定数で､ｸﾗｳﾄﾞ設定されているかどうか
	 *
	 * ｼｽﾃﾑ定数の､CLOUD_TARGET か､CLOUD_BUCKET のどちらかが､
	 * null(ｾﾞﾛ文字列､ﾀﾌﾞ､空白のみ)の場合､false です｡
	 * それ以外は､true を返しますが､正常にｸﾗｳﾄﾞにｱｸｾｽ出来る保証はありません｡
	 * あくまで､ﾘｿｰｽ設定がされているかどうかのみで､判定しています｡
	 *
	 * @og.rev 8.0.0.1 (2021/10/08) ｸﾗｳﾄﾞ修正
	 *
	 * @return ｸﾗｳﾄﾞ設定されていれば true
	 */
	public static boolean useCloud() {
//		return ! StringUtil.isNull( STORAGE,BUCKET );	// どれか一つでも null なら､false

		final boolean isLocal = StringUtil.isNull( STORAGE,BUCKET )
								|| FileOperation.LOCAL.equalsIgnoreCase(STORAGE)
								|| FileOperation.LOCAL.equalsIgnoreCase(BUCKET) ;

		return ! isLocal ;
	}

	/**
	 * ﾛｰｶﾙﾌｧｲﾙをｸﾗｳﾄﾞに移動<del>後､ﾛｰｶﾙﾌｧｲﾙを削除</del>します｡
	 *
	 * ｸﾗｳﾄﾞ設定されている場合､指定のｻﾌﾟﾗｲﾔを実行してﾛｰｶﾙﾌｧｲﾙを取得し､
	 * ｸﾗｳﾄﾞにｺﾋﾟｰ後､ﾛｰｶﾙﾌｧｲﾙを削除します｡
	 * ｸﾗｳﾄﾞ設定されていなければ､何もしません｡
	 *
	 * @og.rev 8.0.0.2 (2021/10/15) ﾛｰｶﾙﾌｧｲﾙとｸﾗｳﾄﾞﾌｧｲﾙ間の移動
	 * @og.rev 8.0.1.0 (2021/10/29) useLocal 属性を追加､ﾌｧｲﾙ削除は行わない｡
	 *
	 * @param useLocal 強制的にﾛｰｶﾙﾌｧｲﾙを使用する場合､true にｾｯﾄします｡
	 * @param supp ﾛｰｶﾙﾌｧｲﾙを生成するｻﾌﾟﾗｲﾔ
	 */
	public static void local2cloud( final boolean useLocal,final Supplier<File> supp ) {
		if( !useLocal && useCloud() ) {
			final File localFile = supp.get();
			final FileOperation cloudFile = create( false,localFile.getPath() );
			FileUtil.copy( localFile, cloudFile );
	//		localFile.delete();
		}
	}

	/**
	 * ｸﾗｳﾄﾞﾌｧｲﾙをﾛｰｶﾙに移動<del>後､ｸﾗｳﾄﾞﾌｧｲﾙを</del>削除します｡
	 *
	 * ｸﾗｳﾄﾞ設定されている場合､指定のｻﾌﾟﾗｲﾔを実行してﾛｰｶﾙﾌｧｲﾙを取得し､
	 * まず､ﾛｰｶﾙﾌｧｲﾙを削除後､ﾛｰｶﾙﾌｧｲﾙの親ﾌｫﾙﾀﾞを作成して､
	 * ｸﾗｳﾄﾞﾌｧｲﾙをﾛｰｶﾙに移動後､ｸﾗｳﾄﾞﾌｧｲﾙを削除します｡
	 * ｸﾗｳﾄﾞ設定されていなければ､何もしません｡
	 *
	 * @og.rev 8.0.0.2 (2021/10/15) ﾛｰｶﾙﾌｧｲﾙとｸﾗｳﾄﾞﾌｧｲﾙ間の移動
	 * @og.rev 8.0.1.0 (2021/10/29) useLocal 属性を追加､ﾌｧｲﾙ削除は行わない｡
	 *
	 * @param useLocal 強制的にﾛｰｶﾙﾌｧｲﾙを使用する場合､true にｾｯﾄします｡
	 * @param supp ﾛｰｶﾙﾌｧｲﾙを生成するｻﾌﾟﾗｲﾔ
	 */
	public static void cloud2local( final boolean useLocal,final Supplier<File> supp ) {
		if( !useLocal && useCloud() ) {
			final File localFile = supp.get();
			final FileOperation cloudFile = create( false,localFile.getPath() );

			localFile.delete();
			final File localParent = localFile.getParentFile();
			if( localParent != null ) { localParent.mkdirs(); }

			FileUtil.copy( cloudFile, localFile );
	//		cloudFile.delete();
		}
	}

	/**
	 * #create(String,String,String)を呼び出してFileOperationを取得します｡
	 * storage,bucketを指定しない場合はｼｽﾃﾑﾘｿｰｽを利用します｡
	 *
	 * 引数をﾃﾞｨﾚｸﾄﾘとして処理します｡
	 * ﾛｰｶﾙﾌｫﾙﾀﾞの場合､ﾃﾞｨﾚｸﾄﾘの作成､ﾃﾞｨﾚｸﾄﾘかどうかのﾁｪｯｸ､書き込みﾁｪｯｸを行います｡
	 *
	 * @og.rev 8.0.0.2 (2021/10/15) ﾛｰｶﾙﾌｧｲﾙとｸﾗｳﾄﾞﾌｧｲﾙ間の移動
	 *
//	 * @param storage ｽﾄﾚｰｼﾞ(AWS など)
//	 * @param bucket ﾊﾞｹｯﾄ名
	 * @param useLocal 強制的にﾛｰｶﾙﾌｧｲﾙを使用する場合､true にｾｯﾄします｡
	 * @param dir ﾃﾞｨﾚｸﾄﾘﾊﾟｽ
	 * @return FileOperationｲﾝｽﾀﾝｽ
	 * @throws IllegalArgumentException 引数のﾃﾞｨﾚｸﾄﾘが作成できない､ﾃﾞｨﾚｸﾄﾘでない､書き込めない場合
	 * @see	#create(boolean,String)
	 */
//	public static FileOperation createDir(final String storage, final String bucket, final String dir) {
	public static FileOperation createDir(final boolean useLocal, final String dir) {
//		final FileOperation cloudDir = create( storage,bucket,dir );
		final FileOperation cloudDir = create( useLocal,dir );

//		if( !useCloud() ) {
		if( useLocal || !useCloud() ) {
			// ｾｰﾌﾞﾃﾞｨﾚｸﾄﾘ 作成
			if( ! cloudDir.exists() && ! cloudDir.mkdirs() ) {
				throw new IllegalArgumentException( "Not make directory: " + dir );
			}

			// Check saveDirectory is truly a directory
			if(!cloudDir.isDirectory()) {
				throw new IllegalArgumentException("Not a directory: " + dir);
			}

			// Check saveDirectory is writable
			if(!cloudDir.canWrite()) {
				throw new IllegalArgumentException("Not writable: " + dir);
			}
		}

		return cloudDir ;
	}
}
