//
// Visuzalization module for TETDM 
// TableDisplay.java Version 0.30
// Copyright(C) 2008 WATARU SUNAYAMA ALL RIGHTS RESERVED.
//
// This program is provided under the license.
// You should read the README file.
//

package module.VisualizationModules.TableDisplay;

import source.*;
import source.TextData.*;
import source.Utility.*;


import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;


public class TableDisplay extends VisualizationModule implements AdjustmentListener, MouseWheelListener
{
	JScrollPane scrollt1;
    JViewport view;
	
	DefaultTableModel tablemodel1;
	JTable table1;
	JTableHeader th;

	String columnNames[];
	int columnNumber;
	String dataNames[];
	int dataNumber;
	double data[][];
    boolean resetData;
	
	int sortedIndex[];
	double values[];
	int lastSortedColumn;
	
	int focusOption;
    
    int highlightColumnList[] = new int[0];
    int highlightColumnlowerBorder[] = new int[0];
    int highlightColumnupperBorder[] = new int[0];
    


    
    boolean selectedData[];
    
    int fontsize = 14;
    
    int rowNumber;
    
    boolean firstColumnLarger = false;
    int panelWidth;
    
	public TableDisplay()
	{
		setModuleID(24);
		setCategoryID(3);
		setUseMode(0);
		setToolType(2);
        
        cancelOperationPanel = true;
	}
	
    public void getPanelWidth()
    {
        panelWidth = getWidth();
    }
    
	public void initializePanel()
	{
		scrollt1 = new JScrollPane();
		view = scrollt1.getViewport();
		add(scrollt1);
		
		scrollt1.addMouseWheelListener(this);
		scrollt1.getVerticalScrollBar().addAdjustmentListener(this);
        

        resetData = false;
	}

	public void initializeData()
	{
		focusOption = 0;
        lastSortedColumn = 0;   // must be here
        selectedData = new boolean[dataNumber];
        
        initializeAttentionKeywords();
	}
	
	public void displayOperations(int optionNumber)
	{
		switch(optionNumber)
		{
            case 4500:
                
                focusOption = getFocusStatus(dataNumber);
                System.out.println("focusOption = "+focusOption);
                
                table1.clearSelection();

                if(focusOption % 4 == 1 || focusOption % 4 == 2)
                {
                    int rn=0;

                    resetHighlightBorder();
                    
                    switch(focusOption)
                    {
                        case 1:
                            rn = getMainFocusSegment();
                            break;
                        case 2:
                            rn = getSubFocusSegment();
                            break;
                        case 5:
                            rn = getMainFocusSentence();
                            break;
                        case 6:
                            rn = getSubFocusSentence();
                            break;
                        case 9:
                            rn = getMainFocusKeyword();
                            break;
                        case 10:
                            rn = getSubFocusKeyword();
                            break;
                    }
                    for(int i=0;i<dataNumber;i++)
                        if(sortedIndex[i] == rn)
                        {
                            table1.setRowSelectionInterval(i,i);
                            break;
                        }
                    selectedData = new boolean[dataNumber];
                    for(int i=0;i<dataNumber;i++)
                        selectedData[i] = false;
                }
                else
                {
                    switch(focusOption)
                    {
                        case 3:
                        case 4:selectedData = getFocusSegments();
                            break;
                        case 7:
                        case 8:selectedData = getFocusSentences();
                            break;
                        case 11:
                        case 12:selectedData = getFocusKeywords();
                            
                            attentionKeywords = text.attention.getAttentionKeywords();  //ATTENTION
                            table1.setDefaultRenderer(Object.class, new ExtendedDefaultTableCellRenderer());
                            break;
                    }

                    highlightLinesBySelectedData();
                    

                }
                break;
				
			case 0:                
				if(scrollt1 == null)
				{
					scrollt1 = new JScrollPane();		//::::::Creating panel
					view = scrollt1.getViewport();
					add(scrollt1);			
				}
				
				tablemodel1 = new DefaultTableModel(columnNames, dataNumber);
				table1 = new JTable(tablemodel1);

				view.setView(table1);
				
				th = table1.getTableHeader();
				th.addMouseListener(listMouseListener);		
				
				table1.addMouseListener(listMouseListener2);	
				
                if(resetData == true)
                {
                    sortedIndex = new int[dataNumber];
                    values = new double[dataNumber];
				
                    for(int i=0;i<dataNumber;i++)
                        sortedIndex[i] = i;
                    
                    resetData = false;
                }
				
				make_contents();
                
                table1.setSelectionBackground(Color.YELLOW);
                table1.setSelectionForeground(Color.BLACK);
                table1.setDefaultRenderer(Object.class, new ExtendedDefaultTableCellRenderer());
                table1.setRowHeight(fontsize);
				break;
                
            case 9:
                fontsize--;
                displayOperations(0);
                break;
                
            case 10:
                fontsize++;
                displayOperations(0);
                break;
                
            //REVERSED WHEN RE-SORT
            case 11:
            case 12:
            case 13:
            case 14:
            case 15:
            case 16:
            case 17:
            case 18:
            case 19:
            case 20:
                rowNumber = optionNumber-11;

                if(rowNumber > columnNames.length)
                    return;
                
                sortColumn(rowNumber);
                break;
                
            case 25:highlightLines();
                break;
                
            //NOT REVERSED WHEN RE-SORT
            case 31:
            case 32:
            case 33:
            case 34:
            case 35:
            case 36:
            case 37:
            case 38:
            case 39:
            case 40:
                rowNumber = optionNumber-31;
                
                if(rowNumber > columnNames.length)
                    return;
                
                lastSortedColumn = -1;
                sortColumn(rowNumber);
                break;
		}		
	}

	public String print_double(double num)
	{
		DecimalFormat df = new DecimalFormat();
		df.applyLocalizedPattern("#####.##");
		
		return df.format(num);
	}
	
	public String print_pattern(double num, String pat)
	{
		DecimalFormat df = new DecimalFormat();
		df.applyLocalizedPattern(pat);
		
		return df.format(num);
	}	
	
	public void make_contents()
	{
		for(int i=0;i<dataNumber;i++)
		{
			table1.setValueAt(dataNames[sortedIndex[i]],i,0);
			
			for(int j=0;j<columnNumber-1;j++)
                table1.setValueAt(print_pattern(data[j][sortedIndex[i]], "#####.#"),i,j+1);
		}
	}
    
    public void setFont()
    {
        fontsize = getFontSize();
    }

	public boolean setData(int dataID, String Names[])
	{
		switch(dataID)
		{
			case 0:		
					columnNumber = Names.length;
					columnNames = Names;
//                System.out.println("Column Number = "+columnNumber);
					return true;
			case 1:
					dataNumber = Names.length;
					dataNames = Names;
//                System.out.println("Data Number by the first column = "+dataNumber);
					return true;
		}
		return false;
	}
	
	public boolean setData(int dataID, double data[][])
	{
		switch(dataID)
		{		
			case 0:	
				dataNumber = data[0].length;
				this.data = data;
                resetData = true;
//                System.out.println("Data Number by values = "+dataNumber);
				return true;
		}
		return false;		
	}
	

    
    public boolean setData(int dataID, int data[])
    {
        switch(dataID)
        {
            case 0: highlightColumnList = data;
                return true;
                
            case 1: highlightColumnlowerBorder = data;
                return true;
                
            case 2: highlightColumnupperBorder = data;
                return true;
        }
        return false;
    }
    
    public boolean setData(int dataID, boolean data)
    {
        switch(dataID)
        {
            case 0:
                firstColumnLarger = data;
                return true;
        }
        return false;
    }
	
	
	public void sortColumn(int n)
	{
//		System.out.println("n="+n+" last="+lastSortedColumn+" dataNumber = "+dataNumber);
			
		int lastIndex = table1.getSelectedRow();
		int lastSortedIndex = -1;
		if(table1.isCellSelected(lastIndex,0))
		{
			table1.changeSelection(lastIndex,0,true,false);
			lastSortedIndex = sortedIndex[lastIndex];
		}
		
		int tempIndex;
		if(n == lastSortedColumn)       //reverse
			for(int i=0;i<dataNumber/2;i++)
			{
				tempIndex = sortedIndex[i];
				sortedIndex[i] = sortedIndex[dataNumber-1-i];
				sortedIndex[dataNumber-1-i] = tempIndex;
			}
		else
		{		
			if(n == 0)                  //reset
				for(int i=0;i<dataNumber;i++)
					sortedIndex[i] = i;
			else                        //sort
			{
				for(int i=0;i<dataNumber;i++)
					values[i] = data[n-1][i];
			
				Qsort.initializeIndex(sortedIndex, dataNumber);
				Qsort.quicksort(values, sortedIndex, dataNumber);
			}
		}

		lastSortedColumn = n;	
		
		make_contents();

		TableColumnModel column = table1.getColumnModel();
		DefaultTableCellRenderer dtr = new DefaultTableCellRenderer();
		dtr.setBackground(Color.yellow);
		for(int i=0;i<columnNumber;i++)
		{
			TableColumn tc = column.getColumn(i);
			if(i == n)
				tc.setHeaderRenderer(dtr);
			else
				tc.setHeaderRenderer(null);
		}
		th.repaint();
        

		if(lastSortedIndex != -1)
		{
			for(int i=0;i<dataNumber;i++)
				if(sortedIndex[i] == lastSortedIndex)
				{
					lastSortedIndex = i;
					break;
				}
			table1.changeSelection(lastSortedIndex,0,true,false);		
		}
	}
    

    

    

    
    class ExtendedDefaultTableCellRenderer extends DefaultTableCellRenderer
    {
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
        {
            super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            
            if (isSelected) {
                setForeground(table.getSelectionForeground());
                setBackground(table.getSelectionBackground());
            } else {
                setForeground(table.getForeground());
                setBackground(table.getBackground());
            }
            
            if(firstColumnLarger)
            {
                getPanelWidth();
                table.getColumnModel().getColumn(0).setPreferredWidth((int)(panelWidth*0.5));
            }
                
            
            
            for(int i=0;i<highlightColumnList.length;i++)   // high light values meet given conditions as ORANGE
                if(column == highlightColumnList[i])
                {
                    double cellValue = Double.parseDouble((String)value);
                    if(cellValue >= highlightColumnlowerBorder[i] && cellValue <= highlightColumnupperBorder[i])
                        setBackground(new Color(255, 164, 0));
                }
            
            if(attentionKeywords[sortedIndex[row]] == true)         //ATTENTION
            {
                 setBackground(Color.green);
            }
            
            setFont(new Font(text.getFontName(), Font.BOLD, fontsize));
 //           table.setRowHeight(fontsize);
            return this;
        }
    }
    
    ///////////FOR DATAMINING USE    highlight lines by given condition
    void highlightLines()
    {
//        System.out.println("dataNumber = "+dataNumber);

        if(selectedData.length != dataNumber)
            selectedData = new boolean[dataNumber];
        
//        for(int i=0;i<highlightColumnList.length;i++)
//            System.out.println("border = "+highlightColumnlowerBorder[0]+","+highlightColumnupperBorder[0]);
        
        for(int i=0;i<dataNumber;i++)
            selectedData[i] = false;
        
        for(int i=0;i<highlightColumnList.length;i++)
            for(int j=0;j<dataNumber;j++)
            {
                double value = Double.parseDouble((String)table1.getValueAt(j, highlightColumnList[i]));
                
//                System.out.println("value = "+value);
                
                if(value >= highlightColumnlowerBorder[i] && value <= highlightColumnupperBorder[i])
                    selectedData[sortedIndex[j]] = true;
            }
        
//        for(int i=0;i<dataNumber;i++)
  //          System.out.println(i+" "+selectedData[i]);
        
        int count=0;
        for(int i=0;i<dataNumber;i++)
            if(selectedData[sortedIndex[i]])
            {
                if(count == 0)
                    table1.setRowSelectionInterval(i,i);
                else
                    table1.addRowSelectionInterval(i,i);
                count++;
            }

        if(selectedData.length == text.segmentNumber)   //For Segments
            copyToFocusSegments();
        
        if(selectedData.length == text.sentenceNumber)  //For Sentences
            copyToFocusSentences();
        
        if(selectedData.length == text.keywordNumber)   //For Keywords
            copyToFocusKeywords();
        
        repaintOthersByFocus();
    }
    
    // highlight lines by focus conditions
    void highlightLinesBySelectedData()
    {
        resetHighlightBorder();
        
        if(selectedData.length == 0)
            return;
        
//        System.out.println("data="+dataNumber+" selected="+selectedData.length+" sorted="+sortedIndex.length);
        
        int count=0;
        for(int i=0;i<dataNumber;i++)
            if(selectedData[sortedIndex[i]])
            {
                if(count == 0)
                    table1.setRowSelectionInterval(i,i);
                else
                    table1.addRowSelectionInterval(i,i);
                count++;
            }
        
        //DO NOT WRITE FOCUS ACTIONS
    }
    /*
    void resetSelection()
    {
        for(int i=dataNumber-1;i>=0;i--)
            table1.changeSelection(i,0,false,false);
    }
    */
    void resetHighlightBorder()
    {
        highlightColumnList = new int[0];
        highlightColumnlowerBorder = new int[0];
        highlightColumnupperBorder = new int[0];
    }
    
    ///////////FOR DATAMINING USE    set focus from given conditions
    void copyToFocusSegments()
    {
        setFocusSegments(selectedData);
    }
    
    void copyToFocusSentences()
    {
        setFocusSentences(selectedData);
    }
    
    void copyToFocusKeywords()
    {
        setFocusKeywords(selectedData);
    }

	//AdjustmentListener
	public void adjustmentValueChanged(AdjustmentEvent e)
	{
		writeBarDragLog();
	}
	
	//MouseWheelListener
	public void mouseWheelMoved(MouseWheelEvent mwe)
	{
		double rotation = mwe.getWheelRotation();
		writeWheelLog(rotation);
	}	
	
	MouseAdapter listMouseListener2 = new MouseAdapter()
	{
        public void mousePressed(MouseEvent e)
        {
            resetHighlightBorder();
        }

        public void mouseReleased(MouseEvent e)    //Click and Dragged
        {
            writeDragLog();
            
            int selected[] = table1.getSelectedRows();
            
            //            System.out.println("SELECTED = "+rn);

            selectedData = new boolean[dataNumber];
            for(int i=0;i<dataNumber;i++)
                selectedData[i] = false;

            if(selected.length == 1)
            {
                int rn = selected[0];

                if (rn >= 0 && rn < dataNumber)
                {
                    if(dataNumber == text.segmentNumber)
                        setMainFocusSegment(sortedIndex[rn],true);
                    if(dataNumber == text.sentenceNumber)
                        setMainFocusSentence(sortedIndex[rn],true);
                    if(dataNumber == text.keywordNumber)
                        setMainFocusKeyword(sortedIndex[rn],true);
                    
                    repaintOthersByFocus();
                    executeOthersByFocus();
                }
            }
            else
            {
                for(int i=0;i<selected.length;i++)
                    selectedData[sortedIndex[selected[i]]] = true;

                if(dataNumber == text.segmentNumber)
                    setFocusSegments(selectedData);
                if(dataNumber == text.sentenceNumber)
                    setFocusSentences(selectedData);
                if(dataNumber == text.keywordNumber)
                    setFocusKeywords(selectedData);

                repaintOthersByFocus();
                executeOthersByFocus();
            }
        }
	}
    ;
	
	MouseAdapter listMouseListener = new MouseAdapter()
	{
		public void mouseClicked(MouseEvent e)      // Header Clicked -> Sort column
		{
			writeClickLog();
	
			TableColumnModel column = table1.getColumnModel();
			int cn = column.getColumnIndexAtX(e.getX());
//			int cn2 = table1.convertColumnIndexToModel(cn);

			if (e.getClickCount() == 1 && cn != -1)
            {
				sortColumn(cn);
                highlightLinesBySelectedData();
            }
		}
	};
}
