/*
 * FullTextSearch
 * 全文検索アプリケーション
 */
package org.logical_paradox.fts.summary;

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;

import org.logical_paradox.fts.InvertedIndexKey;
import org.logical_paradox.fts.KeywordLocation;
import org.logical_paradox.fts.KeywordLocationComparator;
import org.logical_paradox.fts.ParsedKeyLocation;
import org.logical_paradox.fts.SearchResult;

/**
 * サマリーを作成して返す
 */
public class SimpleSummaryGenerator extends SummaryGenerator {
	/*
	 * コンストラクタ
	 */
	public SimpleSummaryGenerator() throws Exception {
		super();
	}

	// 位置情報からサマリーを作成して，結果として返す
	// locations[] - 位置情報
	// founddic - 検索語が共通して存在している文書番号
	public SearchResult[] getSummary(ParsedKeyLocation[] locations, long founddic) {
		// まず，与えられた引数の構造が非常に扱いにくいので，変更する
		// locationsPerSummary[文書no.] = { 位置情報1, 位置情報2, .. 位置情報n }
		// という構造にする．位置情報は，検索語の種類に関係なく，出現位置が順番に格納されるスタイルとする．
		InvertedIndexKey ik = new InvertedIndexKey( "", founddic );
		Map locationsPerSummary = new HashMap();
		for( int i = 0; i < locations.length; i++ ) {
			KeywordLocation[] kl = (KeywordLocation[])locations[i].getLocations();
			for( int j = 0; j < kl.length; j++ ) {
//System.err.println( "docno=" + kl[j]._dicno + ", pos=" + kl[j]._pos );
				if( ik.isTermFoundInDocument( kl[j]._dicno ) == false ) {
					continue;
				}
//System.err.println( "docno=" + kl[j]._dicno + ", pos=" + kl[j]._pos );
				Vector v = (Vector)locationsPerSummary.get(new Integer( kl[j]._dicno ));
				if( v == null ) {
					v = new Vector();
				}
				v.addElement( kl[j] );
				locationsPerSummary.put( new Integer( kl[j]._dicno ), v );
			}
		}

		Iterator it = locationsPerSummary.keySet().iterator();
		SearchResult[] rcs = new SearchResult[ locationsPerSummary.size() ];
		int rcsc = 0;
		Integer intg = null;
		Vector vref = null;
		String rcstr = null;
		KeywordLocation[] lo = null;

		while( it.hasNext() ) {
			intg = (Integer)it.next();
			if( intg != null && (vref = (Vector)locationsPerSummary.get( intg )) != null ) {
				Collections.sort( vref, KeywordLocationComparator.getComparator() );
				lo = (KeywordLocation[])vref.toArray( new KeywordLocation[0] );
				rcstr = getSummaryByLocations( lo );
				rcs[rcsc++] = new SearchResult( lo, rcstr.toString() );
			}
		}

		return rcs;
	}

	// 位置情報からサマリー文字列を切り出して返す
	protected String getSummaryByLocations( KeywordLocation[] lo ) {
		int highScore = 0;
		int lastCnt = 0;
		int lengthOfSummary = 100;
		int basep = 0;
		int score = 1;							// 少なくとも1つは範囲内に含まれているはず

		for( int i = 0; i < lo.length; i++ ) {
			basep = lo[i]._pos;					// 基準点の取得
			score = score <= 1 ? 1 : (score-1);
			for( int j = score; j < lo.length; j++ ) {
				if( basep + lengthOfSummary > lo[j]._pos ) {
					score++;
				}
			}
			if( highScore < score ) {
				// ハイスコア更新
				highScore = score;
				lastCnt = i;
			}
		}

		try {
			// 所定のインターフェースを使って，ドキュメントにアクセスする
			String document = documentManager.getDocument(lo[0]._dicno+1);
			int lastp = 0;
			if( document.length() <= lengthOfSummary + lo[lastCnt]._pos ) {
				lastp = document.length()-1;
			} else {
				lastp = lo[lastCnt]._pos + lengthOfSummary -1;
			}

			String summary = document.substring( lo[lastCnt]._pos, lastp );
			return summary;
		} catch(Exception e) {
			e.printStackTrace();
			return "";
		}
	}
}
