/*
 * blanco Framework
 * Copyright (C) 2004-2007 IGA Tosiki
 * 
 * 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.text.converter;

import java.io.BufferedReader;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;

import blanco.commons.util.BlancoJavaSourceUtil;
import blanco.text.converter.valueobject.BlancoTextConverterSrcTxtChapterStructure;
import blanco.text.converter.valueobject.BlancoTextConverterSrcTxtStructure;

/**
 * 「ソーステキスト」をパースします。
 */
public class BlancoTextConverterSrcTxtParser {
    public BlancoTextConverterSrcTxtStructure parse(
            final BufferedReader argReader) throws IOException {
        final BlancoTextConverterSrcTxtStructure structure = new BlancoTextConverterSrcTxtStructure();

        boolean isBodyStarted = false;

        final StringBuffer strbuf = new StringBuffer();
        for (;;) {
            final String line = argReader.readLine();
            if (line == null) {
                break;
            }

            if (isBodyStarted == false) {
                // 行頭からの開始の場合にのみ判断します。
                // あと : 直後の先頭空白は無視するように変更したい。
                if (line.startsWith("Subject:")) {
                    structure.setSubject(line.substring("Subject:".length())
                            .trim());
                } else if (line.startsWith("Description:")) {
                    structure.setDescription(line.substring(
                            "Description:".length()).trim());
                } else if (line.startsWith("Keywords:")) {
                    structure.setKeywords(line.substring("Keywords:".length())
                            .trim());
                } else if (line.startsWith("Date:")) {
                    try {
                        // final SimpleDateFormat sdFormat = new
                        // SimpleDateFormat(
                        // "yyyy-MM-dd");
                        final SimpleDateFormat sdFormat = new SimpleDateFormat(
                                "yyyy-MM-dd HH:mm:ss");
                        structure.setDate(sdFormat.parse(line.substring(
                                "Date:".length()).trim()));
                    } catch (ParseException e) {
                        try {
                            final SimpleDateFormat sdFormat = new SimpleDateFormat(
                                    "yyyy-MM-dd");
                            structure.setDate(sdFormat.parse(line.substring(
                                    "Date:".length()).trim()));
                        } catch (ParseException e1) {
                            // もはや無視してしまいます。
                            e1.printStackTrace();
                        }

                    }
                } else if (line.trim().length() == 0) {
                    // ボディ領域の開始。
                    isBodyStarted = true;
                } else {
                    // これは あってはなりません。
                    System.out.println("パースに失敗[" + line + "]。無視します。");
                }
            } else {
                // ボディ領域です。
                // 文書構造の解析をおこないます。

                // TODO まずさきに [[]]の解析をおこないます。これ重要。

                if (line.length() > 1 && line.charAt(0) != ' ') {
                    // 1文字目から文字があればタイトル。
                    writeChapter(line, 0, strbuf, structure);
                } else if (line.length() > 2 && line.charAt(0) == ' '
                        && line.charAt(1) != ' ') {
                    writeChapter(line, 1, strbuf, structure);
                } else if (line.length() > 3 && line.charAt(0) == ' '
                        && line.charAt(1) == ' ' && line.charAt(2) != ' ') {
                    writeChapter(line, 2, strbuf, structure);
                } else if (line.length() > 4 && line.charAt(0) == ' '
                        && line.charAt(1) == ' ' && line.charAt(2) == ' '
                        && line.charAt(3) != ' ') {
                    writeChapter(line, 3, strbuf, structure);
                } else {
                    if (line.trim().length() == 0) {
                        // 空行です。
                        flushStringLine(strbuf, structure);
                    } else {
                        // 通常の行です。

                        if (strbuf.length() > 0) {
                            strbuf.append("<br>\n");
                        }

                        if (line.startsWith("    ") == false) {
                            throw new IllegalArgumentException("これは無い[" + line
                                    + "]");
                        }

                        // この時点でエンコードしてから格納します。
                        strbuf.append(BlancoJavaSourceUtil
                                .escapeStringAsJavaDoc(line.substring(4)));
                    }
                }
            }
        }

        flushStringLine(strbuf, structure);

        return structure;
    }

    private void writeChapter(final String line, final int level,
            final StringBuffer strbuf,
            final BlancoTextConverterSrcTxtStructure structure) {
        flushStringLine(strbuf, structure);

        String lineActual = line.substring(level);
        if (lineActual.startsWith("○") || lineActual.startsWith("●")
                || lineActual.startsWith("□") || lineActual.startsWith("■")) {
            lineActual = lineActual.substring(1);
        }

        final BlancoTextConverterSrcTxtChapterStructure chapter = new BlancoTextConverterSrcTxtChapterStructure();
        chapter.setLevel(level);
        chapter.setLine(lineActual);
        structure.getLineList().add(chapter);
    }

    private void flushStringLine(final StringBuffer strbuf,
            final BlancoTextConverterSrcTxtStructure structure) {
        if (strbuf.length() > 0) {
            structure.getLineList().add(strbuf.toString());
            strbuf.setLength(0);
        }
    }
}
