/*******************************************************************************
 * Copyright (c) 2008 IGA Tosiki, NTT DATA BUSINESS BRAINS Corp.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    IGA Tosiki (NTT DATA BUSINESS BRAINS Corp.) - initial API and implementation
 *******************************************************************************/
/*
 * 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.nlpack.generator.frgmnt;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import blanco.nlpack.generator.BlancoNLpackGeneratorConstants;
import blanco.nlpack.generator.BlancoNLpackGeneratorResultDetailUtil;
import blanco.nlpack.generator.csv.io.BlancoCsvIOException;
import blanco.nlpack.generator.csv.io.BlancoNLpackGeneratorResultDetailCsvReader;
import blanco.nlpack.generator.csv.record.BlancoNLpackGeneratorResultDetailCsvRecord;
import blanco.nlpack.generator.message.BlancoNLpackGeneratorMessage;

/**
 * 翻訳フラグメントを扱うクラス。
 * 
 * @author IGA Tosiki
 */
public class BlancoNLpackGeneratorTranslationFragment {
    /**
     * メッセージオブジェクト。
     */
    private final BlancoNLpackGeneratorMessage fMsg = new BlancoNLpackGeneratorMessage();

    /**
     * 翻訳フラグメントのマップ。
     */
    private Map<String, ArrayList<BlancoNLpackGeneratorResultDetailCsvRecord>> fTranslationFragmentMap = null;

    /**
     * 翻訳フラグメントをロードします。
     * 
     * @throws IOException
     *             入出力例外が発生した場合。
     */
    private void load() throws IOException {
        System.out.println("nlpack: translation fragment: load: begin.");

        final int frgmntCount = loadTranslationFragment();

        System.out.println("nlpack: translation fragment: load: end: "
                + frgmntCount + ".");
    }

    private int loadTranslationFragment() throws IOException {
        final InputStream inStream = getClass()
                .getClassLoader()
                .getResourceAsStream(
                        BlancoNLpackGeneratorConstants.FILENAME_TRANSLATION_FRAGMENT);
        if (inStream == null) {
            // TODO メッセージを新規作成。
            throw new IllegalArgumentException(
                    fMsg
                            .getMbebmo01(BlancoNLpackGeneratorConstants.FILENAME_TRANSLATION_FRAGMENT));
        }

        fTranslationFragmentMap = new HashMap<String, ArrayList<BlancoNLpackGeneratorResultDetailCsvRecord>>();
        int frgmntCount = 0;

        // TODO 文字コードは外部に出す必要があります。
        final BlancoNLpackGeneratorResultDetailCsvReader reader = new BlancoNLpackGeneratorResultDetailCsvReader(
                new BufferedReader(new InputStreamReader(inStream,
                        "Windows-31J")));
        try {
            for (;;) {
                if (BlancoNLpackGeneratorResultDetailUtil
                        .checkValidResultDetailRecordByFieldBundleUri(reader
                                .getReader()) == false) {
                    // その行は読み飛ばします。
                    reader.getReader().readLine();
                    continue;
                }

                final BlancoNLpackGeneratorResultDetailCsvRecord record = reader
                        .readRecord();
                if (record == null) {
                    break;
                }

                if (fTranslationFragmentMap.get(record.getBundleUri()) == null) {
                    fTranslationFragmentMap
                            .put(
                                    record.getBundleUri(),
                                    new ArrayList<BlancoNLpackGeneratorResultDetailCsvRecord>());
                }

                final ArrayList<BlancoNLpackGeneratorResultDetailCsvRecord> list = fTranslationFragmentMap
                        .get(record.getBundleUri());
                list.add(record);
                frgmntCount++;
            }
        } catch (BlancoCsvIOException ex) {
            throw new IOException(fMsg.getMbebmo02(ex.toString()));
        } finally {
            reader.close();
        }

        return frgmntCount;
    }

    /**
     * 与えられたuriおよび原文が翻訳フラグメント対象かどうかをチェックします。
     * 
     * @param uri
     *            babel URI。
     * @param argInput
     *            原文。
     * @return 翻訳フラグメント対象ならtrue。
     * @throws IOException
     *             入出力例外が発生した場合。
     */
    public boolean checkTranslationFragment(final String argURI,
            final String argInput) throws IOException {
        if (fTranslationFragmentMap == null) {
            load();
        }

        final ArrayList<BlancoNLpackGeneratorResultDetailCsvRecord> listTranslationFragment = fTranslationFragmentMap
                .get(argURI);
        if (listTranslationFragment == null) {
            return false;
        }
        if (listTranslationFragment.size() == 0) {
            throw new IllegalArgumentException("入ってはならない場所");
        }

        for (int index = 0; index < listTranslationFragment.size(); index++) {
            final BlancoNLpackGeneratorResultDetailCsvRecord record = listTranslationFragment
                    .get(index);
            if (record.getInput().equals(argInput)) {
                return true;
            }
        }

        // はずれ
        // TODO 外部メッセージ化
        System.out.println("警告: 翻訳フラグメントが指定されているのに変換できませんでした: URI[" + argURI
                + "] input[" + argInput + "]");
        return false;
    }

    /**
     * 翻訳フラグメントを利用して、与えられた値を「英語→日本語」へ変換します。
     * 
     * @param argURI
     *            babel URI。
     * @param argInput
     *            原文。
     * @return 日本語文字列。
     */
    public String lookup(final String argURI, final String argInput) {
        if (argURI == null) {
            // TODO 文字列の外部化！
            throw new IllegalArgumentException(
                    "IllegalArgument: BlancoNLpackGeneratorTranslationFragment#lookup(null)");
        }

        if (fTranslationFragmentMap == null) {
            try {
                load();
            } catch (Throwable e) {
                throw new IllegalArgumentException("予期しない例外が発生しました。", e);
            }
        }

        final ArrayList<BlancoNLpackGeneratorResultDetailCsvRecord> listTranslationFragment = fTranslationFragmentMap
                .get(argURI);
        if (listTranslationFragment == null) {
            throw new IllegalArgumentException("入ってはならない場所");
        }
        if (listTranslationFragment.size() == 0) {
            throw new IllegalArgumentException("入ってはならない場所");
        }

        for (int index = 0; index < listTranslationFragment.size(); index++) {
            final BlancoNLpackGeneratorResultDetailCsvRecord record = listTranslationFragment
                    .get(index);
            if (record.getInput().equals(argInput)) {
                return record.getOutput();
            }
        }

        // はずれ
        return null;
    }
}
