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

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import blanco.nlpack.generator.csv.io.BlancoCsvIOException;
import blanco.nlpack.generator.csv.io.BlancoNLpackGeneratorResultDetailCsvReader;
import blanco.nlpack.generator.csv.io.BlancoNLpackGeneratorResultDetailCsvWriter;
import blanco.nlpack.generator.csv.record.BlancoNLpackGeneratorResultDetailCsvRecord;
import blanco.nlpack.generator.task.valueobject.BlancoNLpackGeneratorMergeResultDetailProcessInput;

/**
 * 一方を基準としてResultDetailをマージします。
 * 
 * @author IGA Tosiki
 */
public class BlancoNLpackGeneratorMergeResultDetail {
    protected BlancoNLpackGeneratorMergeResultDetailProcessInput fInput;

    public void process(
            final BlancoNLpackGeneratorMergeResultDetailProcessInput input)
            throws IOException, BlancoCsvIOException {
        fInput = input;

        final BlancoNLpackGeneratorResultDetailCsvWriter writer = new BlancoNLpackGeneratorResultDetailCsvWriter(
                new BufferedWriter(new FileWriter((input.getTargetfile()))));
        writer.writeTitle();

        merge(writer);

        writer.close();
    }

    private void merge(final BlancoNLpackGeneratorResultDetailCsvWriter writer)
            throws IOException, BlancoCsvIOException {
        final Map mapRight = new HashMap();
        loadResultDetail(new File(fInput.getSourceright()), mapRight);

        final BlancoNLpackGeneratorResultDetailCsvReader reader = new BlancoNLpackGeneratorResultDetailCsvReader(
                new BufferedReader(new FileReader(fInput.getSourceleft())));
        for (int index = 0;; index++) {
            if (checkValidRecordByUri(reader.getReader()) == false) {
                continue;
            }

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

            final BlancoNLpackGeneratorResultDetailCsvRecord recordMerge = new BlancoNLpackGeneratorResultDetailCsvRecord();
            recordMerge.setBundleUri(recordLeft.getBundleUri());
            recordMerge.setKey(recordLeft.getKey());
            recordMerge.setInput(recordLeft.getInput());
            if (mapRight.get(recordLeft.getBundleUri()) == null
                    && mapRight.get(getBundleNameWithLocale(recordLeft
                            .getBundleUri())) == null) {
                // 右辺には見当たらず。無視されたリソースと判断。
                recordMerge.setAction("ignore");
            } else {
                // 右辺に発見。
                Object objFind = mapRight.get(recordLeft.getBundleUri());
                if (objFind == null) {
                    objFind = mapRight.get(getBundleNameWithLocale(recordLeft
                            .getBundleUri()));
                }
                final BlancoNLpackGeneratorResultDetailCsvRecord recordRight = (BlancoNLpackGeneratorResultDetailCsvRecord) objFind;
                recordMerge.setOutput(recordRight.getInput());
                if (recordMerge.getInput().equals(recordMerge.getOutput())) {
                    // 一致している
                    recordMerge.setAction("miss");
                    // TODO 実際には、除外辞書との突き合わせが必要。
                } else {
                    recordMerge.setAction("hit");
                }
            }
            writer.writeRecord(recordMerge);
        }
        reader.close();
    }

    private static String getBundleNameWithLocale(final String bundleName)
            throws IOException {
        // babel://
        String strUrl = "https://" + bundleName.substring("https://".length());
        URL url = new URL(strUrl);
        // System.out.println(url.getHost() + ".nl_ja");
        // System.out.println(url.getPath().substring(0,
        // url.getPath().length() - ".properties.".length()));
        // System.out.println(url.getQuery());

        String result = "babel://"
                + url.getHost()
                + ".nl_ja"
                + url.getPath().substring(0,
                        url.getPath().length() - ".properties".length())
                + "_ja.properties";
        if (url.getQuery().length() > 0) {
            result += "?" + url.getQuery();
        }

        // System.out.println(result);
        return result;
    }

    private static void loadResultDetail(final File fileResultDetail,
            final Map map) throws IOException, BlancoCsvIOException {
        final BlancoNLpackGeneratorResultDetailCsvReader reader = new BlancoNLpackGeneratorResultDetailCsvReader(
                new BufferedReader(new FileReader(fileResultDetail)));
        int lineCounter = 0;
        for (;; lineCounter++) {
            if (checkValidRecordByUri(reader.getReader()) == false) {
                continue;
            }

            final BlancoNLpackGeneratorResultDetailCsvRecord record = reader
                    .readRecord();
            if (record == null) {
                break;
            }
            map.put(record.getBundleUri(), record);

            // System.out.println(record.getBundleUri());
        }
        reader.close();
        System.out.println(lineCounter + "件読み込み");
    }

    private static boolean checkValidRecordByUri(
            final BufferedReader readerInner) throws IOException {
        // "babel: 以外の行は無視します。
        readerInner.mark(8);
        final char[] buf = new char[7];
        final int len = readerInner.read(buf);
        readerInner.reset();

        if (len < 7) {
            // 無視
        } else {
            if (new String(buf).equals("\"babel:") == false) {
                // 処理不能な行。この行は読み飛ばします。
                readerInner.readLine();
                return false;
            }
        }
        return true;
    }
}
