/*******************************************************************************
 * 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.xliff.util.task;

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

import blanco.commons.util.BlancoStringUtil;
import blanco.properties.BlancoPropertiesUtil;
import blanco.xliff.BlancoXliffUtil;
import blanco.xliff.stringgroup.BlancoXliffStateStringGroup;
import blanco.xliff.util.task.valueobject.BlancoXliffUtilExtractAlttransDiffProcessInput;
import blanco.xliff.valueobject.BlancoXliff;
import blanco.xliff.valueobject.BlancoXliffAltTrans;
import blanco.xliff.valueobject.BlancoXliffFile;
import blanco.xliff.valueobject.BlancoXliffNote;
import blanco.xliff.valueobject.BlancoXliffTransUnit;

public class BlancoXliffUtilExtractAlttransDiffProcessImpl implements
        BlancoXliffUtilExtractAlttransDiffProcess {
    private BlancoXliffUtilExtractAlttransDiffProcessInput fInput = null;

    private BlancoXliff fXliffDiff = new BlancoXliff();

    public int execute(
            final BlancoXliffUtilExtractAlttransDiffProcessInput input)
            throws IOException, IllegalArgumentException {
        fInput = input;

        final File fileXliffdir = new File(fInput.getXliffdir());
        final File[] files = fileXliffdir.listFiles();
        if (files == null) {
            return 0;
        }
        for (int index = 0; index < files.length; index++) {
            if (files[index].isFile() == false) {
                continue;
            }
            if (files[index].getName().endsWith(".xlf")) {
                process(fileXliffdir, files[index]);
            }
        }

        return 0;
    }

    private void process(final File fileXliffdir, final File fileTarget)
            throws IOException {

        final String bundleSymbolicName = fileTarget.getName().substring(0,
                fileTarget.getName().length() - ".xlf".length());

        final BlancoXliff fXliff = BlancoXliffUtil.getXliffInstance(
                fileXliffdir, bundleSymbolicName);

        for (int indexFile = 0; indexFile < fXliff.getFileList().size(); indexFile++) {
            final BlancoXliffFile file = fXliff.getFileList().get(indexFile);
            processFile(file);
        }

        final File fileTargetfile = new File(fInput.getTargetfile());
        if (fileTargetfile.getParentFile().exists() == false) {
            fileTargetfile.getParentFile().mkdirs();
        }
        BlancoXliffUtil.saveXliffInstance(fXliffDiff, new File(fileTargetfile
                .getParentFile().getAbsolutePath()), fileTargetfile.getName()
                .substring(0,
                        fileTargetfile.getName().length() - ".xlf".length()));
    }

    private void processFile(final BlancoXliffFile file) {
        for (int index = 0; index < file.getBody().getTransUnitList().size(); index++) {
            final BlancoXliffTransUnit transUnit = file.getBody()
                    .getTransUnitList().get(index);
            processTransUnit(transUnit);
        }
    }

    private void processTransUnit(final BlancoXliffTransUnit transUnit) {
        if (transUnit.getTranslate() == false) {
            // 除外
            return;
        }

        // omitマークのチェック。
        for (int indexNote = 0; indexNote < transUnit.getNoteList().size(); indexNote++) {
            final BlancoXliffNote note = transUnit.getNoteList().get(indexNote);
            if ("blanconlpackgenerator.omit.tm".equals(note.getFrom())) {
                // 除外。
                return;
            }
        }

        if (BlancoPropertiesUtil.isPreferenceKeywords(transUnit.getId())) {
            // プリファランス・キーワードは処理対象外です。
            if (fInput.getVerbose()) {
                System.out.println("uri[" + transUnit.getId()
                        + "] はプリファランス・キーワードであるため除外します。");
            }
            return;
        }

        if (transUnit.getTarget() == null) {
            // target 無しについては処理対象外。
            return;
        }
        if (BlancoStringUtil.null2Blank(transUnit.getTarget().getTarget())
                .trim().length() == 0) {
            // target の文字列無しについても処理対象外。
            return;
        }

        switch (new BlancoXliffStateStringGroup().convertToInt(BlancoStringUtil
                .null2Blank(transUnit.getTarget().getState()))) {
        case BlancoXliffStateStringGroup.NEW:
        case BlancoXliffStateStringGroup.NEEDS_TRANSLATION:
            // これら state については処理対象外。
            return;
        }

        boolean isEqual = false;
        for (int index = 0; index < transUnit.getAltTransList().size(); index++) {
            final BlancoXliffAltTrans altTrans = transUnit.getAltTransList()
                    .get(index);
            if (BlancoStringUtil.null2Blank(fInput.getToolid()).equals(
                    altTrans.getToolId()) == false) {
                // 対象 toolid 以外は処理しません。
                continue;
            }

            if (transUnit.getTarget().getTarget().equals(
                    altTrans.getTarget().getTarget())) {
                isEqual = true;
                continue;
            }

            if (false) {
                // あいまい一致を許容する場合。
                String unitTarget = transUnit.getTarget().getTarget();
                String altTarget = altTrans.getTarget().getTarget();

                // 空白をあいまい化。
                unitTarget = BlancoStringUtil
                        .replace(unitTarget, " ", "", true);
                altTarget = BlancoStringUtil.replace(altTarget, " ", "", true);

                // 日本語句点。
                unitTarget = BlancoStringUtil
                        .replace(unitTarget, "。", "", true);
                altTarget = BlancoStringUtil.replace(altTarget, "。", "", true);

                // セミコロン。
                unitTarget = BlancoStringUtil
                        .replace(unitTarget, ";", "", true);
                altTarget = BlancoStringUtil.replace(altTarget, ";", "", true);

                // 中黒
                unitTarget = BlancoStringUtil
                        .replace(unitTarget, "・", "", true);
                altTarget = BlancoStringUtil.replace(altTarget, "・", "", true);

                if (unitTarget.equals(altTarget)) {
                    isEqual = true;
                    continue;
                }

            }
        }

        if (isEqual == false) {
            if (fXliffDiff.getFileList().size() == 0) {
                final BlancoXliffFile xliffFile = new BlancoXliffFile();
                fXliffDiff.getFileList().add(xliffFile);
            }

            final BlancoXliffFile xliffFile = fXliffDiff.getFileList().get(0);

            // 同じ source 文字列の他の登録がないかどうかチェックします。
            for (int indexExist = 0; indexExist < xliffFile.getBody()
                    .getTransUnitList().size(); indexExist++) {
                final BlancoXliffTransUnit registered = xliffFile.getBody()
                        .getTransUnitList().get(indexExist);
                if (registered.getSource().equals(transUnit.getSource())) {
                    // 既に登録あり。
                    for (int indexNote = 0; indexNote < transUnit.getNoteList()
                            .size(); indexNote++) {
                        // note を転送します。
                        registered.getNoteList().add(
                                transUnit.getNoteList().get(indexNote));
                    }
                    return;
                }
            }

            xliffFile.getBody().getTransUnitList().add(transUnit);
        }
    }
}
