/*
 * Copyright (c) 2009 The openGion Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package org.opengion.fukurou.taglet;

import com.sun.javadoc.Tag;

import org.opengion.fukurou.util.FileUtil;
import org.opengion.fukurou.util.StringUtil;

import java.io.File;
import java.io.PrintWriter;
import java.io.IOException;

/**
 * Tag 情報を出力する PrintWriter 相当クラスです。
 *
 * @version  4.0
 * @author   Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public final class DocletTagWriter {
	private final PrintWriter outFile ;
	private final boolean rtn2br ;			// 改行コードを <br/>に置換するかどうか

	private static final String ENCODE = "UTF-8" ;

	/** リターンコード  System.getProperty("line.separator")  */
	public static final String CR = System.getProperty("line.separator");
	/** HTML上のブレーク  &lt;br&gt; + CR  */
	public static final String BR = "&lt;br&gt;" + CR ;

	/**
	 * Doclet のエントリポイントメソッドです。
	 *
	 * 初期エンコードで出力します。
	 *
	 * @param file	出力ファイル名
	 * @throws IOException なんらかのエラーが発生した場合。
	 */
	public DocletTagWriter( final String file ) throws IOException {
		this( file,ENCODE,false );
	}

	/**
	 * Doclet のエントリポイントメソッドです。
	 *
	 * @param file		出力ファイル名
	 * @param encode	エンコード
	 * @throws IOException なんらかのエラーが発生した場合。
	 */
	public DocletTagWriter( final String file,final String encode ) throws IOException {
		this( file,encode,false );
	}

	/**
	 * Doclet のエントリポイントメソッドです。
	 *
	 * @param file		出力ファイル名
	 * @param encode	エンコード
	 * @param r2b 		改行コードを BRタグに置換するかどうか
	 * @throws IOException なんらかのエラーが発生した場合。
	 */
	public DocletTagWriter( final String file,final String encode,final boolean r2b ) throws IOException {
		outFile = FileUtil.getPrintWriter( new File( file ),encode );
		rtn2br = r2b;
	}

	/**
	 * 出力ファイルをクロースします。
	 *
	 */
	public void close() {
		outFile.close();
	}

	/**
	 * 可変長の文字列引数を取り、文字列を出力します。
	 * 文字列の最後に改行が入ります。
	 *
	 * @param str String...
	 */
	public void printTag( final String... str ) {
		for( int i=0; i<str.length; i++ ) {
			if( rtn2br ) { outFile.print( str[i].replaceAll( CR,BR ) ); }
			else		 { outFile.print( str[i] ); }
		}
		outFile.println();
	}

	/**
	 * タグ配列を受け取り、タグ出力します。
	 *
	 * 従来は、Tagが、１つの場合と配列の場合で改行出力を分けていましたが、改行しないことにします。
	 *
	 * @og.rev 5.5.4.1 (2012/07/06) {&#064;og.value package.class#field} の処理 対応
	 * @og.rev 5.5.4.1 (2012/07/06) DocletUtil.htmlFilter → StringUtil.htmlFilter に変更
	 * @og.rev 5.5.4.2 (2012/07/13) タグ出力の最後に改行を入れておきます。
	 * @og.rev 5.5.5.6 (2012/08/31) @og.tag などに @og.value が含まれている場合の処理を追加
	 * @og.rev 5.5.5.6 (2012/08/31) @og.tag などに @og.value が含まれている場合の処理を追加
	 * @og.rev 5.6.3.3 (2013/04/19) @og.tag などに @og.doc03Link が含まれている場合の処理を追加
	 * @og.rev 5.7.1.1 (2013/12/13) 一旦文字列に入れて、rtn2br の判定処理を行います。
	 *
	 * @param tag タグ配列
	 */
	public void printTag( final Tag[] tag ) {
		for( int i=0; i<tag.length; i++ ) {
			String tagName = tag[i].name();
			String data = "";
			// {@og.value package.class#field} の処理を行います。
			if( tagName.equalsIgnoreCase( "@og.value" ) ) {
//				outFile.print( DocletUtil.valueTag( tag[i]) );
				data = DocletUtil.valueTag( tag[i] );
			}
			// 5.6.3.3 (2013/04/19) {@og.doc03Link ・・・} の処理を行います。
			else if( tagName.equalsIgnoreCase( "@og.doc03Link" ) ) {
//				outFile.print( DocletUtil.doc03LinkTag( tag[i]) );
				data = DocletUtil.doc03LinkTag( tag[i] );
			}
			// 5.5.5.6 (2012/08/31) @og.tag などに @og.value が含まれている場合の処理を追加
			else if( ! tagName.equalsIgnoreCase( "Text" ) ) {
				printTag( tag[i].inlineTags() );
			}
			else {
//				String data = DocletUtil.htmlFilter( tag[i].text() );
//				String data = StringUtil.htmlFilter( tag[i].text() ).trim();		// 5.5.4.1 (2012/07/06) DocletUtil → StringUtil に変更
				data = StringUtil.htmlFilter( tag[i].text() ).trim();		// 5.5.4.1 (2012/07/06) DocletUtil → StringUtil に変更

//				if( rtn2br ) {
//					outFile.print( data.replaceAll( CR,BR ) );
////					outFile.print( BR );
//				}
//				else {
////					outFile.println( data );
//					outFile.print( data );
//				}
			}
			if( rtn2br ) {
				outFile.print( data.replaceAll( CR,BR ) );
			}
			else {
				outFile.print( data );
			}
		}
//		outFile.println();				// 5.5.4.2 (2012/07/13) タグ出力の最後に改行
	}

	/**
	 * 文字列引数を ２つと、タグ配列を受け取り、タグ出力します。
	 *
	 * @param str1	第一文字列
	 * @param tag	タグ配列
	 * @param str3	第三文字列
	 */
	public void printTag( final String str1,final Tag[] tag, final String str3 ) {
		outFile.print( str1 );
		printTag( tag );
		outFile.println( str3 );
	}

	/**
	 * タグ配列を受け取り、タグ出力します。
	 *
	 * @param tag Tag[]
	 */
//	public void printTag( final Tag[] tag ) {
//		if( tag.length == 1 ) {
//			String data = DocletUtil.htmlFilter( tag[0].text() );
//			if( rtn2br ) { outFile.print( data.replaceAll( CR,BR ) ); }
//			else		 { outFile.print( data ); }
//		}
//		else {
//			for( int i=0; i<tag.length; i++ ) {
//				String data = DocletUtil.htmlFilter( tag[i].text() );
//				if( rtn2br ) {
//					outFile.print( data.replaceAll( CR,BR ) );
//					outFile.print( BR );
//				}
//				else {
//					outFile.println( data );
//				}
//			}
//		}
//	}

	/**
	 * タグ配列を受け取り、タグ出力します。
	 * 複数のタグを出力する場合に、カンマ区切り文字で連結します。
	 *
	 * @og.rev 5.5.4.1 (2012/07/06) DocletUtil.htmlFilter → StringUtil.htmlFilter に変更
	 *
	 * @param tag タグ配列
	 */
	public void printCSVTag( final Tag[] tag ) {
		for( int i=0; i<tag.length; i++ ) {
//			String data = DocletUtil.htmlFilter( tag[i].text() );
			String data = StringUtil.htmlFilter( tag[i].text() );		// 5.5.4.1 (2012/07/06) DocletUtil → StringUtil に変更
			if( i > 0 ) { outFile.print( "," ); }
			outFile.print( data );
		}
	}

	/**
	 * タグ配列を受け取り、タグ出力します。
	 * ここでは、タグ毎にタグの名称と内容を出力し、改行を行います。
	 * 特殊処理：ここでは、og.rev タグは取り込みません。
	 *
	 * @og.rev 5.5.4.1 (2012/07/06) DocletUtil.htmlFilter → StringUtil.htmlFilter に変更
	 *
	 * @param tag タグ配列
	 */
	public void printTagsInfo( final Tag[] tag ) {
		for( int i=0; i<tag.length; i++ ) {
			String tagName = tag[i].name();
			if( tagName.equalsIgnoreCase( "@og.rev" ) ) {
				continue;
			}
			outFile.print( tagName );
			outFile.print( " " );
//			outFile.print( DocletUtil.htmlFilter( tag[i].text() ) );
			outFile.print( StringUtil.htmlFilter( tag[i].text() ) );		// 5.5.4.1 (2012/07/06) DocletUtil → StringUtil に変更
			if( rtn2br ) { outFile.print( BR ); }
			else		 { outFile.println(); }
		}
	}

	/**
	 * 文字列引数を ２つと、タグ配列を受け取り、先頭一文字のタグ出力します。
	 *
	 * @param str1	第一文字列
	 * @param tag	タグ配列
	 * @param str3	第三文字列
	 */
	public void printChar( final String str1,final Tag[] tag, final String str3 ) {
		outFile.print( str1 );
		if( tag.length > 0 ) {
			String str = tag[0].text();
			if( str != null && str.length() > 0 ) {
				outFile.print( str.charAt(0) );
			}
		}
		outFile.println( str3 );
	}
}
