/*******************************************************************************
 * 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 java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.StringTokenizer;

import blanco.commons.util.BlancoStringUtil;
import blanco.xliff.BlancoXliffUtil;
import blanco.xliff.stringgroup.BlancoXliffStateStringGroup;
import blanco.xliff.util.task.valueobject.BlancoXliffUtilStatisticsProcessInput;
import blanco.xliff.valueobject.BlancoXliff;
import blanco.xliff.valueobject.BlancoXliffFile;
import blanco.xliff.valueobject.BlancoXliffTransUnit;

public class BlancoXliffUtilStatisticsProcessImpl implements
        BlancoXliffUtilStatisticsProcess {
    private BlancoXliff fXliff = null;

    private int fXlfCount = 0;

    private int fFileCount = 0;

    private int fTotalCount = 0;

    private int fActiveCount = 0;

    private int fTranslatedCount = 0;

    private int fNeedsTranslationCount = 0;

    private int fNewCount = 0;

    private int fNoTargetCount = 0;

    private static final String WORD_DELIMITER = " ,.!?:;/|";

    private int fActiveWordsCount = 0;

    private int fRemainsWordsCount = 0;

    public int execute(final BlancoXliffUtilStatisticsProcessInput input)
            throws IOException, IllegalArgumentException {
        final File fileXliffdir = new File(input.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]);
            }
        }

        // 進捗率
        String strTranslatedRate = "";
        String strWordsPerKeyRate = "";
        String strRemainsWordsPerKeyRate = "";

        try {
            strTranslatedRate = BigDecimal.valueOf(fTranslatedCount * 100)
                    .setScale(2).divide(BigDecimal.valueOf(fActiveCount),
                            BigDecimal.ROUND_DOWN).toString();
            strWordsPerKeyRate = BigDecimal.valueOf(fActiveWordsCount)
                    .setScale(2).divide(BigDecimal.valueOf(fActiveCount),
                            BigDecimal.ROUND_DOWN).toString();
            strRemainsWordsPerKeyRate = BigDecimal.valueOf(fRemainsWordsCount)
                    .setScale(2).divide(
                            BigDecimal.valueOf(fNoTargetCount + fNewCount
                                    + fNeedsTranslationCount),
                            BigDecimal.ROUND_DOWN).toString();
        } catch (ArithmeticException e) {
            // 例外はもみ消します。
        }

        final NumberFormat numFormat = NumberFormat.getNumberInstance();
        System.out.println("[xliff]");
        System.out
                .println("- xlf :"
                        + BlancoStringUtil.padLeft(numFormat.format(fXlfCount),
                                6, ' '));
        System.out.println("- file:"
                + BlancoStringUtil
                        .padLeft(numFormat.format(fFileCount), 6, ' '));

        System.out.println("[trans-unit]");
        System.out.println("- total     :"
                + BlancoStringUtil.padLeft(numFormat.format(fTotalCount), 10,
                        ' '));
        System.out.println("- active    :"
                + BlancoStringUtil.padLeft(numFormat.format(fActiveCount), 10,
                        ' '));
        System.out.println("- translated:"
                + BlancoStringUtil.padLeft(numFormat.format(fTranslatedCount),
                        10, ' ') + " " + "(" + strTranslatedRate + "%)");
        System.out.println("- needs-tran:"
                + BlancoStringUtil.padLeft(numFormat
                        .format(fNeedsTranslationCount), 10, ' '));
        System.out.println("- new       :"
                + BlancoStringUtil
                        .padLeft(numFormat.format(fNewCount), 10, ' '));
        System.out.println("- no_target :"
                + BlancoStringUtil.padLeft(numFormat.format(fNoTargetCount),
                        10, ' '));

        System.out.println("[words]");
        System.out.println("- active    :"
                + BlancoStringUtil.padLeft(numFormat.format(fActiveWordsCount),
                        10, ' ') + " (" + strWordsPerKeyRate + " words/key)");
        System.out.println("- remains   :"
                + BlancoStringUtil.padLeft(
                        numFormat.format(fRemainsWordsCount), 10, ' ') + " ("
                + strRemainsWordsPerKeyRate + " words/key)");

        return 0;
    }

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

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

        fXliff = BlancoXliffUtil.getXliffInstance(fileXliffdir,
                bundleSymbolicName);

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

    private void processFile(final BlancoXliffFile file) {
        fFileCount++;

        for (int index = 0; index < file.getBody().getTransUnitList().size(); index++) {
            final BlancoXliffTransUnit transUnit = file.getBody()
                    .getTransUnitList().get(index);

            // 全 trans-unit
            fTotalCount++;

            if (transUnit.getTranslate() == false) {
                // 除外項目。
            } else {
                // 翻訳対象 trans-unit
                fActiveCount++;
                processTransUnit(transUnit);
            }
        }
    }

    private void processTransUnit(final BlancoXliffTransUnit transUnit) {
        if (transUnit.getTarget() == null) {
            fNoTargetCount++;
            fRemainsWordsCount += new StringTokenizer(transUnit.getSource(),
                    WORD_DELIMITER).countTokens();
        } else {
            switch (new BlancoXliffStateStringGroup()
                    .convertToInt(BlancoStringUtil.null2Blank(transUnit
                            .getTarget().getState()))) {
            case BlancoXliffStateStringGroup.NEW:
                fNewCount++;
                fRemainsWordsCount += new StringTokenizer(
                        transUnit.getSource(), WORD_DELIMITER).countTokens();
                break;
            case BlancoXliffStateStringGroup.X_NOTARGET:
                fNoTargetCount++;
                fRemainsWordsCount += new StringTokenizer(
                        transUnit.getSource(), WORD_DELIMITER).countTokens();
                break;
            case BlancoXliffStateStringGroup.NEEDS_TRANSLATION:
                fNeedsTranslationCount++;
                fRemainsWordsCount += new StringTokenizer(
                        transUnit.getSource(), WORD_DELIMITER).countTokens();
                break;
            case BlancoXliffStateStringGroup.NEEDS_REVIEW_TRANSLATION:
            case BlancoXliffStateStringGroup.FINAL:
            case BlancoXliffStateStringGroup.X_REVIEWED:
            default:
                fTranslatedCount++;
                break;
            }
        }

        fActiveWordsCount += new StringTokenizer(transUnit.getSource(),
                WORD_DELIMITER).countTokens();
    }
}
