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;

/**
 * クオートがもれているCSVファイルのクオートを回復するためのユーティリティ
 * 
 * 試験がまったく足りていません。
 */
public class NormalizeResultDetailCsvFile {

    public static void main(final String[] args) throws IOException {
        new File("./tmp/quote").mkdirs();
        final File[] files = new File("./tmp").listFiles();
        for (int index = 0; index < files.length; index++) {
            if (files[index].isFile() == false) {
                continue;
            }
            if (files[index].getName().endsWith(".csv") == false) {
                continue;
            }
            new NormalizeResultDetailCsvFile().process(files[index], new File(
                    "./tmp/quote/" + files[index].getName()));
        }
    }

    private void process(final File input, final File output)
            throws IOException {
        System.out.println("NormalizeResultDetailCsvFile: " + input.getName());

        final BufferedReader reader = new BufferedReader(new FileReader(input));
        final BufferedWriter writer = new BufferedWriter(new FileWriter(output));

        boolean isProcessQuote = false;
        for (;;) {
            reader.mark(1);
            final int read = reader.read();
            if (read < 0) {
                break;
            }

            final char readChar = (char) read;

            if (readChar == '"') {
                // クオート開始。
                writer.write(readChar);
                processQuote(reader, writer);
                isProcessQuote = true;
            } else if (readChar == ',') {
                // 空の項目と判断します。
                if (isProcessQuote == false) {
                    writer.write('"');
                    writer.write('"');
                }
                writer.write(readChar);
                isProcessQuote = false;
            } else if (readChar == '\n') {
                // 空の項目と判断します。
                if (isProcessQuote == false) {
                    writer.write('"');
                    writer.write('"');
                }
                writer.write(readChar);
                isProcessQuote = false;
            } else {
                reader.reset();
                processNonQuote(reader, writer);
                isProcessQuote = false;
            }
        }

        writer.close();
        reader.close();
    }

    private void processQuote(final BufferedReader reader,
            final BufferedWriter writer) throws IOException {
        // 現在クオート中です。
        for (;;) {
            reader.mark(1);
            final int read = reader.read();
            if (read < 0) {
                reader.reset();
                break;
            }

            final char readChar = (char) read;

            if (readChar == '"') {
                // これが クオートの終端か、あるいはクオートのエスケープかについて判断の必要があります。
                reader.mark(1);
                final int read2 = reader.read();
                if (read2 < 0) {
                    throw new IllegalArgumentException("ありえない");
                }

                writer.write(readChar);

                final char readChar2 = (char) read2;
                if (readChar2 == '"') {
                    // これは終端ではなく、単なるエスケープでした。
                    // 読み込んだ１文字は破棄します。
                } else {
                    // 終端と判断します。
                    reader.reset();
                    break;
                }
            } else {
                writer.write(readChar);
            }
        }
    }

    private void processNonQuote(final BufferedReader reader,
            final BufferedWriter writer) throws IOException {
        // 現在項目中です。
        writer.write('"');
        for (;;) {
            reader.mark(1);
            final int read = reader.read();
            if (read < 0) {
                reader.reset();
                writer.write('"');
                break;
            }

            final char readChar = (char) read;

            if (readChar == '\n') {
                // 終了
                writer.write('"');
                writer.write(readChar);
                break;
            }
            if (readChar == ',') {
                writer.write('"');
                writer.write(readChar);
                break;
            }

            if (readChar == '\r') {
                // 無視
                continue;
            }

            writer.write(readChar);
        }
    }
}
