/*******************************************************************************
 * 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.util.HashMap;
import java.util.Map;

import blanco.nlpack.generator.BlancoNLpackGeneratorResultDetailUtil;
import blanco.nlpack.generator.csv.io.BlancoCsvIOException;
import blanco.nlpack.generator.csv.io.BlancoNLpackGeneratorDiffResultDetailCsvWriter;
import blanco.nlpack.generator.csv.io.BlancoNLpackGeneratorResultDetailCsvReader;
import blanco.nlpack.generator.csv.record.BlancoNLpackGeneratorDiffResultDetailCsvRecord;
import blanco.nlpack.generator.csv.record.BlancoNLpackGeneratorResultDetailCsvRecord;
import blanco.nlpack.generator.task.valueobject.BlancoNLpackGeneratorDiffResultDetailProcessInput;

/**
 * ResultDetailを比較します。
 * 
 * @author IGA Tosiki
 */
public class BlancoNLpackGeneratorDiffResultDetail {
    protected BlancoNLpackGeneratorDiffResultDetailProcessInput fInput;

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

        final BlancoNLpackGeneratorDiffResultDetailCsvWriter writer = new BlancoNLpackGeneratorDiffResultDetailCsvWriter(
                new BufferedWriter(new FileWriter((input.getTargetdiff()))));
        writer.writeTitle();

        diffAddChange(writer);
        diffRemove(writer);

        writer.close();
    }

    private void diffAddChange(
            final BlancoNLpackGeneratorDiffResultDetailCsvWriter writer)
            throws IOException, BlancoCsvIOException {
        final Map<String, BlancoNLpackGeneratorResultDetailCsvRecord> mapLeft = new HashMap<String, BlancoNLpackGeneratorResultDetailCsvRecord>();
        BlancoNLpackGeneratorResultDetailUtil.loadResultDetail(new File(fInput
                .getSourceleft()), mapLeft);

        final BlancoNLpackGeneratorResultDetailCsvReader reader = new BlancoNLpackGeneratorResultDetailCsvReader(
                new BufferedReader(new FileReader(fInput.getSourceright())));
        for (int index = 0;; index++) {
            if (BlancoNLpackGeneratorResultDetailUtil
                    .checkValidResultDetailRecordByFieldBundleUri(reader
                            .getReader()) == false) {
                // その行は読み飛ばします。
                reader.getReader().readLine();
                continue;
            }

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

            final BlancoNLpackGeneratorDiffResultDetailCsvRecord recordDiff = new BlancoNLpackGeneratorDiffResultDetailCsvRecord();
            recordDiff.setBundleUri(recordRight.getBundleUri());
            recordDiff.setKey(recordRight.getKey());
            recordDiff.setRightAction(recordRight.getAction());
            recordDiff.setRightInput(recordRight.getInput());
            recordDiff.setRightOutput(recordRight.getOutput());
            if (mapLeft.get(recordRight.getBundleUri()) == null) {
                // 左辺には見当たらず。
                recordDiff.setDiff("add");
            } else {
                // 左辺に発見。
                final BlancoNLpackGeneratorResultDetailCsvRecord recordLeft = (BlancoNLpackGeneratorResultDetailCsvRecord) mapLeft
                        .get(recordRight.getBundleUri());
                recordDiff.setLeftAction(recordLeft.getAction());
                recordDiff.setLeftInput(recordLeft.getInput());
                recordDiff.setLeftOutput(recordLeft.getOutput());
                if (recordLeft.getInput().equals(recordRight.getInput())
                        && recordLeft.getOutput().equals(
                                recordRight.getOutput())) {
                    // 一致している
                    recordDiff.setDiff("equal");
                    if (fInput.getReportequal() == false) {
                        continue;
                    }
                } else {
                    final StringBuffer strbuf = new StringBuffer("change.");
                    if (recordLeft.getInput().equals(recordRight.getInput()) == false) {
                        strbuf.append('i');
                    }
                    if (recordLeft.getOutput().equals(recordRight.getOutput()) == false) {
                        strbuf.append('o');
                    }
                    // 最大で change.io となります。
                    recordDiff.setDiff(strbuf.toString());
                }
            }
            writer.writeRecord(recordDiff);
        }
        reader.close();
    }

    private void diffRemove(
            final BlancoNLpackGeneratorDiffResultDetailCsvWriter writer)
            throws IOException, BlancoCsvIOException {
        final Map<String, BlancoNLpackGeneratorResultDetailCsvRecord> mapRight = new HashMap<String, BlancoNLpackGeneratorResultDetailCsvRecord>();
        BlancoNLpackGeneratorResultDetailUtil.loadResultDetail(new File(fInput
                .getSourceright()), mapRight);

        final BlancoNLpackGeneratorResultDetailCsvReader reader = new BlancoNLpackGeneratorResultDetailCsvReader(
                new BufferedReader(new FileReader(fInput.getSourceleft())));
        for (int index = 0;; index++) {
            if (BlancoNLpackGeneratorResultDetailUtil
                    .checkValidResultDetailRecordByFieldBundleUri(reader
                            .getReader()) == false) {
                // その行は読み飛ばします。
                reader.getReader().readLine();
                continue;
            }

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

            final BlancoNLpackGeneratorDiffResultDetailCsvRecord recordDiff = new BlancoNLpackGeneratorDiffResultDetailCsvRecord();
            recordDiff.setBundleUri(recordLeft.getBundleUri());
            recordDiff.setKey(recordLeft.getKey());
            recordDiff.setLeftAction(recordLeft.getAction());
            recordDiff.setLeftInput(recordLeft.getInput());
            recordDiff.setLeftOutput(recordLeft.getOutput());
            if (mapRight.get(recordLeft.getBundleUri()) == null) {
                // 右辺には見当たらず。
                recordDiff.setDiff("remove");
                writer.writeRecord(recordDiff);
            }
        }
        reader.close();
    }
}
