//
// Mining module for TETDM 
// CValue.java Version 1.0
// Copyright(C) 2013 YASUFUMI TAKAMA All RIGHTS RESERVED.
// This program is provided under the license.
// You Should read the README file.
//

package module.MiningModules.CValue;

import module.MiningModules.TermMiningBase.*;
import java.util.*;
import java.lang.Math.*;

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

@SuppressWarnings("serial")
public class CValue extends TermMiningBase
{
	int LIST_LEN;	// # of words to be returned
	String[] tlist;
	WordList nGramList;
	WordList allNGramList;
	WordList cValueList;
	HashMap<String, Double> cvalueHash;
	boolean isLoadKeyword;
	
	public CValue()
	{
//		super();
		setModuleID(46);
//		initializeData();
        setCategoryID(2);
        pairingVisualizationID = new int[]{25};
	}
	
	public void initializeData(){// initialize class field variable
		LIST_LEN=150;
		tlist = new String[1];
		tlist[0] = "NoData";
		isLoadKeyword = false;
	}
	
	public int[] SetValues() // return list of values correspondings to keywords
	{
				
		if(!isLoadKeyword){
			int[] a = new int[1];
			a[0] = -1;
			return a;
		}else {
			int[] values = new int[tlist.length];
			for(int i=0; i<tlist.length; i++){
				int F = 0;
				for(int k=0; k<cValueList.size(); k++){
					String str = ngramWordToString(cValueList.get(k));
					String stFind = tlist[i];
					if(str.indexOf(stFind)>=0){
						F++;
					}
				}
				values[i] = F;
			}
			return values;
		}
	}
	
	public String[] SetKeyword()
	{
		WordList singleWordList = new WordList();
		for(int i=0; i<text.segmentNumber;i++){
			for(int j=0; j<text.segment[i].sentenceNumber;j++){
				Word singleWord = new Word();
				for(int k=0; k<text.segment[i].sentence[j].wordNumber;k++){
						char c = text.segment[i].sentence[j].word[k].charAt(0);
						if(c >= 0x8340 && c <= 0x8396 ){
							singleWord.append(new Word(i, j, k));
						}else if(!singleWord.isEmpty){
							singleWordList.add(new NGramWord(singleWord));
							singleWord = new Word();
						}
						
						if(text.segment[i].sentence[j].wordIDList[k]>=0){
							singleWord = new Word(i, j, k);
							singleWordList.add(new NGramWord(singleWord));
							singleWord = new Word();
						}
				}
			}
		}
		if(singleWordList.size()==0){
			return tlist;
		}

		allNGramList = new WordList();
		cValueList = new WordList();
		NGramWord appendList = new NGramWord();
		appendList = singleWordList.get(0);
		for(int i=0;i < singleWordList.size()-1;i++){
			NGramWord cValueListMae = singleWordList.get(i);
			NGramWord cValueListUsiro = singleWordList.get(i+1);
			if(isBiGram(cValueListMae.getLastWord(), cValueListUsiro.getLastWord())){
				appendList.add(cValueListUsiro.getLastWord());
			}else {
				cValueList.add(appendList);
				appendList= new NGramWord();
				appendList.add(cValueListUsiro.getLastWord());
			}
		}
		cValueList.add(appendList);

		nGramList = singleWordList;
		while(nGramList.size()>1){
			WordList inputWordList = nGramList;
			allNGramList.addAll(nGramList);
			nGramList = new WordList();
			
			for(int i=0; i<inputWordList.size()-1;i++){
				NGramWord nGramWordMae = inputWordList.get(i);
				NGramWord nGramWordUsiro = inputWordList.get(i+1);
				
				if(isBiGram(nGramWordMae.getLastWord(), nGramWordUsiro.getLastWord())){
					NGramWord res = new NGramWord();
					res.addAll(nGramWordMae);
					res.add(nGramWordUsiro.getLastWord());
					nGramList.add(res);
				}
			}
		}

		cvalueHash = new HashMap<String,Double>();
		for(int i=0; i<allNGramList.size(); i++){
			NGramWord nowWord = allNGramList.get(i);
			int L = nowWord.size();
			if(L<2) {
				continue;
			}
			if(cvalueHash.containsKey(ngramWordToString(nowWord))){
				continue;
			}
			ArrayList<NGramWord> cList = new ArrayList<NGramWord>();
			double cValue = 0d;
			int N=0;
			int T = 0;
			for(int j=0; j<cValueList.size(); j++){
				NGramWord check = cValueList.get(j);
				if(ngramWordToString(check).equals(ngramWordToString(nowWord))){
					N++;
				}
				if((check.size() > nowWord.size())
					&& (ngramWordToString(check).indexOf(ngramWordToString(nowWord))>=0)){
					T++;
					if(!cList.contains(check)){
						cList.add(check);
					}
				}
			}
			N = T+N;
			int C = cList.size();
			if(C != 0){
				cValue = (double)(L-1)*((double)N - T/(double)C);
			}else{
				cValue = 0;
			}
			cvalueHash.put(ngramWordToString(nowWord), cValue);
		}
		
		List<Map.Entry> entries = new ArrayList<Map.Entry>(cvalueHash.entrySet());
		Collections.sort(entries, new Comparator(){
		    public int compare(Object o1, Object o2){
		        Map.Entry e1 =(Map.Entry)o1;
		        Map.Entry e2 =(Map.Entry)o2;
		        return (-1)*((Double)e1.getValue()).compareTo((Double)e2.getValue());
		    }
		});
		try{
			File file = new File(myModulePath + "score.txt");
			PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file, false)));
			
			int len=setListLength(entries);
			if(len>0){
				tlist = new String[len];
				for(int i=0; i<len; i++){
					tlist[i] = (String)(entries.get(i).getKey());
				}
				isLoadKeyword = true;
			}
			pw.println((String)("# of words="+(entries.size())));
			for(int i=0; i<entries.size(); i++){
				pw.println((String)(entries.get(i).getKey()) +": score_"+ (Double)(entries.get(i).getValue()));

			}

			pw.close();
		}catch(IOException e){
	      		System.out.println(e);
	   	}
		return tlist;
	}	
	
	String wordToString(Word word){
		String stWord = "";
		for(int i=word.wordNumberStart; i<=word.wordNumberEnd; i++){
			stWord += text.segment[word.segmentNumber].sentence[word.sentenceNumber].word[i];
		}
		return stWord;
	}
	
	String ngramWordToString(NGramWord ngramWord){
		String word = "";
		for(int i=0; i<ngramWord.size(); i++){
			word += wordToString(ngramWord.get(i));
		}
		return word;
	}
	
	Boolean isBiGram(Word ngwMae, Word ngwUsiro){
		if((ngwMae.segmentNumber == ngwUsiro.segmentNumber)
			&& (ngwMae.sentenceNumber == ngwUsiro.sentenceNumber)
			&& ( (ngwMae.wordNumberEnd+1) == ngwUsiro.wordNumberStart) ){
			return true;
		}
		return false;
	}

	class Word{
		public int segmentNumber;
		public int sentenceNumber;
		public int wordNumberStart;
		public int wordNumberEnd;
		public boolean isEmpty;
		public Word(){
			this.isEmpty = true;
		}
		public Word(int segmentNum, int sentenceNum, int wordNum){
			this.segmentNumber = segmentNum;
			this.sentenceNumber = sentenceNum;
			this.wordNumberStart = wordNum;
			this.wordNumberEnd = wordNum;
			this.isEmpty = false;
		}
		public void append(Word word){
			if(this.isEmpty){
				this.segmentNumber = word.segmentNumber;
				this.sentenceNumber = word.sentenceNumber;
				this.wordNumberStart = word.wordNumberStart;
				this.isEmpty = false;
			}
			this.wordNumberEnd = word.wordNumberStart;
		}
	}
	
	class NGramWord extends ArrayList<Word>{
		public NGramWord(){
			;
		}
		
		public NGramWord(Word word){
			this.add(word);
		}
		
		public Word getLastWord(){
			return this.get(this.size()-1);
		}
		
	}
	
	class WordList extends ArrayList<NGramWord>{
		public WordList(){
			;
		}
	}

	int setListLength(List<Map.Entry> entries){
		int i=0;
		int limit = Math.min(entries.size(),LIST_LEN);
		while(i<limit){
			if((Double)(entries.get(i).getValue())<=0)
				break;
			i++;
		}
		return i;
	}
}
