/*
 * blanco Framework
 * Copyright (C) 2008 NTT DATA BUSINESS BRAINS CORPORATION
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 */
package blanco.sed.task;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringReader;

import blanco.commons.util.BlancoStringUtil;
import blanco.sed.BlancoSed;
import blanco.sed.BlancoSedConstants;
import blanco.sed.task.valueobject.BlancoSedProcessInput;

/**
 * 処理 [BlancoSedProcess]インタフェース。
 * 
 * @author IGA Tosiki
 */
public class BlancoSedProcessImpl implements BlancoSedProcess {
    /**
     * クラスをインスタンス化して処理を実行する際のエントリポイントです。
     * 
     * @param input
     *            処理の入力パラメータ。
     * @return 処理の実行結果。
     * @throws IOException
     *             入出力例外が発生した場合。
     * @throws IllegalArgumentException
     *             入力値に不正が見つかった場合。
     */
    public int execute(final BlancoSedProcessInput input) throws IOException,
            IllegalArgumentException {
        System.out.println("- " + BlancoSedConstants.PRODUCT_NAME + " ("
                + BlancoSedConstants.VERSION + ")");

        final File fileInput = new File(input.getInput());
        final File fileOutput = new File(input.getOutput());
        if (fileInput.exists() == false) {
            throw new IllegalArgumentException("sed: 入力ファイルが見つかりません: "
                    + fileInput.getAbsolutePath());
        }
        if (fileInput.isFile() == false) {
            throw new IllegalArgumentException("sed: 入力ファイルが実はファイルではありません: "
                    + fileInput.getAbsolutePath());
        }
        if (fileInput.canRead() == false) {
            throw new IllegalArgumentException("sed: 入力ファイルが読み込めません: "
                    + fileInput.getAbsolutePath());
        }
        if (fileOutput.exists()) {
            if (fileOutput.isFile() == false) {
                throw new IllegalArgumentException(
                        "sed: 出力ファイルが既に存在し、しかもファイルではありません: "
                                + fileOutput.getAbsolutePath());
            }
            if (fileOutput.canWrite() == false) {
                throw new IllegalArgumentException("sed: 出力ファイルに書き込みできません: "
                        + fileOutput.getAbsolutePath());
            }
        }

        if (BlancoStringUtil.null2Blank(input.getScriptfile()).length() > 0) {
            final File fileScriptFile = new File(input.getScriptfile());
            if (fileScriptFile.exists() == false) {
                throw new IllegalArgumentException("sed: スクリプトファイルが存在しません: "
                        + fileScriptFile.getAbsolutePath());
            }
            if (fileScriptFile.isFile() == false) {
                throw new IllegalArgumentException(
                        "sed: スクリプトファイルが実はファイルではありません: "
                                + fileScriptFile.getAbsolutePath());
            }
        }
        if (BlancoStringUtil.null2Blank(input.getScript()).length() == 0
                && BlancoStringUtil.null2Blank(input.getScriptfile()).length() == 0) {
            throw new IllegalArgumentException(
                    "scriptとscriptfileのいずれも指定されていません。いずれか一方を指定してください。");
        }
        if (BlancoStringUtil.null2Blank(input.getScript()).length() > 0
                && BlancoStringUtil.null2Blank(input.getScriptfile()).length() > 0) {
            throw new IllegalArgumentException(
                    "scriptとscriptfileの両方が指定されています。いずれか一方だけを指定してください。");
        }

        BufferedReader reader = null;
        BufferedWriter writer = null;
        BufferedReader readerScriptFile = null;
        try {
            if (BlancoStringUtil.null2Blank(input.getScript()).length() > 0) {
                readerScriptFile = new BufferedReader(new StringReader(input
                        .getScript()));
            } else {
                readerScriptFile = new BufferedReader(new InputStreamReader(
                        new FileInputStream(input.getScriptfile()), input
                                .getEncoding()));
            }

            reader = new BufferedReader(new InputStreamReader(
                    new FileInputStream(input.getInput()), input.getEncoding()));
            writer = new BufferedWriter(new OutputStreamWriter(
                    new FileOutputStream(input.getOutput()), input
                            .getEncoding()));

            BlancoSed.process(reader, writer, readerScriptFile);

        } finally {
            if (reader != null) {
                reader.close();
            }
            if (writer != null) {
                writer.close();
            }
            if (readerScriptFile != null) {
                readerScriptFile.close();
            }
        }

        return BlancoSedBatchProcess.END_SUCCESS;
    }
}
