package blanco.encryption.task;

import java.io.File;
import java.io.IOException;

import blanco.encryption.BlancoEncryptionConstants;
import blanco.encryption.BlancoEncryptionDesede;
import blanco.encryption.task.valueobject.BlancoEncryptionDesedeBatchProcessInput;

/**
 * バッチ処理クラス。
 */
public class BlancoEncryptionDesedeBatchProcess extends
        AbstractBlancoEncryptionDesedeBatchProcess {
    /**
     * 暗号化後のファイルに付与される文字列。
     */
    private static final String ENCRYPTED_FILE_EXT = ".blancodesede";

    /**
     * 具体的なバッチ処理内容を記述するためのメソッドです。
     * 
     * このメソッドに実際の処理内容を記述します。
     * 
     * @param input
     *            バッチ処理の入力パラメータ。
     * @return バッチ処理の終了コード。
     */
    public int process(BlancoEncryptionDesedeBatchProcessInput input) {
        System.out.println("- " + BlancoEncryptionConstants.PRODUCT_NAME + " ("
                + BlancoEncryptionConstants.VERSION + ")");

        try {
            // TODO ファイル存在チェック。
            final File fileInputDir = new File(input.getInputDir());
            if (fileInputDir.exists() == false) {
                System.out.println("指定の入力ディレクトリ[" + input.getInputDir()
                        + "]は見つかりません。処理中断します。");
                return END_ILLEGAL_ARGUMENT;
            }

            final File fileOutputDir = new File(input.getOutputDir());
            if (fileOutputDir.exists() == false) {
                if (fileOutputDir.mkdirs() == false) {
                    throw new IllegalArgumentException("ディレクトリ["
                            + input.getOutputDir() + "]作成失敗");
                }
            } else {
                if (fileOutputDir.isFile()) {
                    throw new IllegalArgumentException("ディレクトリ["
                            + input.getOutputDir() + "]は実際にはファイルでした。");
                }
            }

            if (fileInputDir.getCanonicalPath().equals(
                    fileOutputDir.getCanonicalPath())) {
                throw new IllegalArgumentException("入力ディレクトリ["
                        + input.getInputDir() + "]と出力ディレクトリ["
                        + input.getOutputDir()
                        + "]とは同一ディレクトリです。異なるディレクトリを指定してください。");
            }

            final File[] files = fileInputDir.listFiles();

            for (int index = 0; index < files.length; index++) {
                if (files[index].isFile() == false) {
                    // ファイル以外は処理しません。
                    continue;
                }

                // TODO そのファイルが読めるかどうかチェックが必要。

                final BlancoEncryptionDesede desede = new BlancoEncryptionDesede();

                if (files[index].getName().endsWith(ENCRYPTED_FILE_EXT) == false) {
                    // 暗号化
                    final File fileOutput = new File(fileOutputDir
                            .getAbsolutePath()
                            + "/" + files[index].getName() + ENCRYPTED_FILE_EXT);
                    System.out.println("blanco.encrypt["
                            + files[index].getAbsolutePath() + "] -> ["
                            + fileOutput.getName() + "]");
                    desede.encrypt(files[index], fileOutput, input
                            .getPassword());
                } else {
                    // 復号化
                    final File fileOutput = new File(fileOutputDir
                            .getAbsolutePath()
                            + "/"
                            + files[index].getName().substring(
                                    0,
                                    files[index].getName().length()
                                            - ENCRYPTED_FILE_EXT.length()));
                    System.out.println("blanco.decrypt["
                            + files[index].getAbsolutePath() + "] -> ["
                            + fileOutput.getName() + "]");
                    desede.decrypt(files[index], fileOutput, input
                            .getPassword());
                }
            }

            return END_SUCCESS;
        } catch (IOException ex) {
            // ex.printStackTrace();
            throw new IllegalArgumentException("入出力例外が発生しました:" + ex.toString());
        }
    }
}
