/*******************************************************************************
 * 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;

import java.io.BufferedWriter;
import java.io.IOException;

import blanco.commons.io.Native2AsciiWriter;
import blanco.nlpack.generator.csv.record.BlancoNLpackGeneratorResultDetailCsvRecord;
import blanco.nlpack.generator.dictionary.BlancoNLpackGeneratorOmitDictionary;
import blanco.nlpack.generator.dictionary.BlancoNLpackGeneratorPleiadesDictionary;
import blanco.nlpack.generator.frgmnt.BlancoNLpackGeneratorTranslationFragment;
import blanco.nlpack.generator.message.BlancoNLpackGeneratorMessage;

/**
 * プロパティファイルを、リーダ・ライタを経由して(英語から)各国語へと値を変換します。
 * 
 * @author IGA Tosiki
 */
class BlancoNLpackGeneratorPropertiesConverter {
    /**
     * メッセージオブジェクト。
     */
    private final BlancoNLpackGeneratorMessage fMsg = new BlancoNLpackGeneratorMessage();

    /**
     * Pleiades辞書のインスタンス。
     */
    private BlancoNLpackGeneratorPleiadesDictionary fPleiadesDictionary = new BlancoNLpackGeneratorPleiadesDictionary();

    /**
     * blancoNLpackGeneratorとしての除外辞書インスタンス。
     */
    private BlancoNLpackGeneratorOmitDictionary fOmitDictionary = new BlancoNLpackGeneratorOmitDictionary();

    /**
     * 翻訳フラグメントのインスタンス。
     */
    private BlancoNLpackGeneratorTranslationFragment fTranslationFragment = new BlancoNLpackGeneratorTranslationFragment();

    /**
     * ヒットした件数。
     */
    private int fReplaceHitCount = 0;

    /**
     * ニモーニック変換をした件数。
     */
    private int fReplaceMnemonicCount = 0;

    /**
     * 除外した件数。
     */
    private int fReplaceOmitCount = 0;

    /**
     * ミスした件数。
     */
    private int fReplaceMissCount = 0;

    public void resetReplaceCount() {
        // 呼び出されるごとにカウンタをリセットします。
        fReplaceHitCount = 0;
        fReplaceMnemonicCount = 0;
        fReplaceOmitCount = 0;
        fReplaceMissCount = 0;
    }

    /**
     * ヒットした件数を取得します。
     * 
     * @return ヒットした件数。
     */
    public int getReplaceHitCount() {
        return fReplaceHitCount;
    }

    /**
     * ニモーニック変換した件数を取得します。
     * 
     * @return ニモーニック変換した件数。
     */
    public int getReplaceMnemonicCount() {
        return fReplaceMnemonicCount;
    }

    /**
     * 除外した件数を取得します。
     * 
     * @return 除外した件数。
     */
    public int getReplaceOmitCount() {
        return fReplaceOmitCount;
    }

    /**
     * ミスした件数を取得します。
     * 
     * @return ミスした件数。
     */
    public int getReplaceMissCount() {
        return fReplaceMissCount;
    }

    /**
     * 辞書をひきます。
     * 
     * @param bundleURI
     * @param strKey
     * @param inputValue
     * @param writer
     * @param record
     * @return
     * @throws IOException
     */
    public boolean lookup(final String bundleURI, final String strKey,
            final String inputValue, final BufferedWriter writer,
            final BlancoNLpackGeneratorResultDetailCsvRecord record)
            throws IOException {
        final String bundleURIwithKey = bundleURI + "?key=" + strKey;

        record.setBundleUri(bundleURIwithKey);
        record.setKey(strKey);
        record.setInput(inputValue);

        if (fTranslationFragment.checkTranslationFragment(bundleURIwithKey,
                inputValue)) {
            final String outputValue = fTranslationFragment.lookup(
                    bundleURIwithKey, inputValue);

            // 出力値をセット！
            writer.write(Native2AsciiWriter
                    .encodeNative2AsciiValue(outputValue));
            fReplaceHitCount++;
            // フラグメント置換をマーク。
            record.setAction("hit.f");
            record.setOutput(outputValue);
            return true;
        }

        final String outputValue = fPleiadesDictionary.lookup(inputValue);
        if (outputValue == null) {
            throw new IllegalArgumentException(fMsg.getMbebc003(bundleURI,
                    strKey));
        }

        if (fOmitDictionary.checkOmitURI(bundleURI)
                || fOmitDictionary.checkOmitURI(bundleURIwithKey)) {
            // URIベースのomit判定で除外対象とわかった場合。

            // 入力されたvalueをそのまま出力。
            writer
                    .write(Native2AsciiWriter
                            .encodeNative2AsciiValue(inputValue));
            fReplaceOmitCount++;
            record.setAction("omit.u");
            return false;
        }

        if (fOmitDictionary.checkOmitPhrase(inputValue)) {
            // 文字列だけを見た場合にフレーズ除外対象とわかった場合。

            // 入力されたvalueをそのまま出力。
            writer
                    .write(Native2AsciiWriter
                            .encodeNative2AsciiValue(inputValue));
            fReplaceOmitCount++;
            record.setAction("omit.p");
            return false;
        }

        if (fOmitDictionary.checkOmitString(inputValue)) {
            // 文字列だけを見た場合に除外対象とわかった場合。

            // 入力されたvalueをそのまま出力。
            writer
                    .write(Native2AsciiWriter
                            .encodeNative2AsciiValue(inputValue));
            fReplaceOmitCount++;
            record.setAction("omit.s");
            return false;
        }

        if (fPleiadesDictionary.getFoundStatus() == BlancoNLpackGeneratorPleiadesDictionary.STATUS_NOT_FOUND) {
            // 辞書に見当たらなかった場合。

            // 入力されたvalueをそのまま出力。
            writer
                    .write(Native2AsciiWriter
                            .encodeNative2AsciiValue(inputValue));
            fReplaceMissCount++;
            record.setAction("miss");
            return false;
        }

        if (fPleiadesDictionary.getFoundStatus() == BlancoNLpackGeneratorPleiadesDictionary.STATUS_MNEMONIC_CHANGED) {
            // ニモーニック変換のみ実施された場合。

            if (fOmitDictionary.checkOmitMnemonicOnlyURI(bundleURI)
                    || fOmitDictionary
                            .checkOmitMnemonicOnlyURI(bundleURIwithKey)) {
                // ニモーニック変換のみの除外ファイルに合致する場合。

                // これは変換してはダメ。
                // 入力されたvalueをそのまま出力。
                writer.write(Native2AsciiWriter
                        .encodeNative2AsciiValue(inputValue));
                fReplaceOmitCount++;
                record.setAction("omit.m");
                return false;
            }

            // 出力値をセット！
            writer.write(Native2AsciiWriter
                    .encodeNative2AsciiValue(outputValue));
            fReplaceMnemonicCount++;
            // 置換をマーク。
            record.setAction("mnemon");
            record.setOutput(outputValue);
            return true;
        }

        if (fPleiadesDictionary.getFoundStatus() == BlancoNLpackGeneratorPleiadesDictionary.STATUS_FOUND) {
            // 辞書からの引き当てに成功した場合。

            // 出力値をセット！
            writer.write(Native2AsciiWriter
                    .encodeNative2AsciiValue(outputValue));
            fReplaceHitCount++;
            // 置換をマーク。
            record.setAction("hit.p");
            record.setOutput(outputValue);
            return true;
        }

        throw new IllegalArgumentException("想定されない箇所に入ってきました。");
    }
}
