/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package twitter.hashtag;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import twitter.manage.TweetConfiguration;
import twitter.manage.TweetManager;
import twitter.util.MultiSortedMap;
import twitter4j.Status;

/**
 * 指定したキーワードに関係のあるハッシュタグを検索する
 * @author nishio
 */
public class HashtagSearcher {

    //twitter管理クラス
    private TweetManager tweetManager;
    //ハッシュタグのパターン
    private static final String HASHTAG_PATTERN =
    	TweetConfiguration.HASHTAG_PATTERN;
    //検索情報数
    private static final int MAX_SEARCH_NUM = 200;

    /**
     *
     * @param tweetManager
     */
    public HashtagSearcher(TweetManager tweetManager) {
        this.tweetManager = tweetManager;
    }

    /**
     * 検索したワードに関するハッシュタグを出現頻度準に取得
     * @param searchWord
     * @return 見つからなかったらnull, 見つかったらkey=出現回数, value = 出現ワードが出現頻度降順に並べられて出力される
     */
    public MultiSortedMap<Integer, String> getDescendantHashtagCount(String searchWord) {
        MultiSortedMap<Integer, String> counter = null;
        Map<String, Integer> searchWordCounter = calcSearchedHashtagCount(searchWord);
        if( searchWordCounter != null ) {
            //検索ワード見つかった時
            counter = new MultiSortedMap<Integer, String>(new Comparator<Integer>(){

                //keyを降順にソート
                @Override
                public int compare(Integer t, Integer t1) {
                    return t1.compareTo(t);
                }

            });

            Set<String> keyset = searchWordCounter.keySet();
            for( String key : keyset ) {
                //keyとvalueを逆転させる
                Integer val = searchWordCounter.get(key);
                counter.add(val, key);
            }
        }
        return counter;
    }

    /**
     * 指定したワードに関連するハッシュタグをツイッターから取得
     * @return 検索結果が見つからない場合はnullを返す
     *         見つかった場合は，key=検索ワード, val = 出現数
     */
    public Map<String, Integer> calcSearchedHashtagCount(String searchWord) {
        //指定したワードをツイッターから検索
        List<Status> searchResult = this.tweetManager.getSearchResult(MAX_SEARCH_NUM, searchWord);
        if( searchResult == null || searchResult.size() == 0 ) {
            return null;
        }
        //ハッシュタグ出現回数
        Map<String, Integer> counter = new HashMap<String, Integer>();

        for(Status s : searchResult ) {
            //検索してきたワードを含むテキスト
            String message = s.getText();
            if( message != null ) {
                //検索してきた1ツイートのハッシュタグ出現回数を取得
                Map<String, Integer> oneTweet = getHashtagCount(message);
                //出現回数
                Set<String> keyset = oneTweet.keySet();

                for(String key : keyset) {
                    //いままでその単語が出現していたかどうか
                    Integer count = counter.get(key);
                    if( count == null ) {
                        count = new Integer(0);
                    }
                    //いままで出現していた単語数に新しく出現した単語数を足す
                    count = count + oneTweet.get(key);
                    counter.put(key, count);
                }
            }
        }

        if( counter.size() == 0 ) {
            return null;
        }
        return counter;
    }

    /**
     * 指定したメッセージに含まれるハッシュタグの出現回数を返す
     * @param message
     * @return key = キーワード, value = 出現回数
     */
    public Map<String, Integer> getHashtagCount(String message) {
        // #で始まる情報
        Pattern userPtn = Pattern.compile(HASHTAG_PATTERN);
        Matcher matcher = userPtn.matcher(message);

        // #で始まる情報一覧を抜き出す
        Map<String, Integer> counter = new HashMap<String, Integer>();

        while (matcher.find()) {
            //ハッシュタグを探しカウントしていく
            String str = matcher.group(0);
            Integer val = counter.get(str);
            if( val == null ) {
                val = new Integer(0);
            }
            val = val + 1;
            counter.put(str, val);
        }
        return counter;
    }
}
