//***********************************************************
//*
//* File:           TournamentResults.java
//* Author:         Abhinav Kamra
//* Contact:        kamra-at-cs.columbia.edu
//* Update:         9.14.2002
//*
//* Description:    Tournament results analysis class
//*                 responsible for computing statistics
//*                 and generating a table model.
//*
//***********************************************************

package ui;

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

public final class TournamentResults implements IFCTournamentResults {

    ArrayList       _listeners;
    Class           _cellclass;
    final String    _CNULL_STRING = "[Null]";
    IFCGameRecord[] _games;
    String[][]      _table;
    NumberFormat    _nf;
    PlayerEntry[]   _entries;
    double[]        _versusopp;
    double[]        _oppname;
    static final String _CNAME      = "Tournament Results";
    static final int _CRANK         = 0;
    static final int _CSCORE        = 1;
    static final int _CTIME         = 2;
    static final int[] _CVALUE_COLUMNS = { _CRANK, _CSCORE, _CTIME };
    static final String[] _CNAMES = { "Player", "Rank", "Score", "Time Consumed" };

    public TournamentResults(IFCGameRecord[] __games) throws Exception {
        Class[] players;
        ClassScorePair[] pairs;
        double[] ranks;
        PlayerEntry pe;
        double[] scores;
        double[] times;
        int[] winners;
        int k;
        int _MAXI;
        int _MAXJ;
        int _MAXK;

        _listeners = new ArrayList();
        _cellclass = new String().getClass();
        _games = __games;

        _MAXI = _games.length;
        for (int i=0; i < _MAXI; i++) {

	FileWriter wr = new FileWriter("Results/" + _games[i].gameFile() + "." + _games[i].cookieCopies());

            players = _games[i].players();
            scores = _games[i].scores();
            times = _games[i].times();
            winners = Util.minIndex(scores);
            _MAXJ = players.length;

            pairs = new ClassScorePair[_MAXJ];
            for (int p=0; p < _MAXJ; p++) {
                pairs[p] = new ClassScorePair(players[p], scores[p]);
            }
            ranks = Util.ranks(pairs);

		_entries = new PlayerEntry[_MAXJ];
		for (int j=0; j < _MAXJ; j++)
		{
			_entries[j] = new PlayerEntry(players[j]);
			_entries[j].set(_CRANK, ranks[j]);
			_entries[j].set(_CSCORE, scores[j]);
			_entries[j].set(_CTIME, times[j]);
		} // End of all players for one game

		_nf = NumberFormat.getInstance();
		_nf.setMinimumFractionDigits(3);
		_nf.setMaximumFractionDigits(5);
		_nf.setMinimumIntegerDigits(1);
		Arrays.sort(_entries, new PlayerEntrySorter(_CRANK));
		printTable(wr, _games[i].gameFile(), _games[i].cookieCopies());

	wr.close();
        } // End for all games
    }

public void printTable(FileWriter wr, String gamefile, int copies) throws Exception
{
        int _MAXI = _entries.length;
        int _MAXJ = _CVALUE_COLUMNS.length;
        String[] toks;


        _table = new String[_MAXI][_CNAMES.length];
        _MAXJ = _CVALUE_COLUMNS.length;
        for (int i=0; i < _MAXI; i++)
	{
            toks = Util.split(".", _entries[i].toString());
            _table[i][0] = toks[toks.length-1];
            for (int j=0; j < _MAXJ; j++) {
                _table[i][j+1] = _nf.format(_entries[i].get(j));
            }
        }

        for (int i=0; i < _MAXI; i++)
	{
		wr.write(gamefile + ",\t" + copies + ",\t" + _entries[i].toString() + ",\t" + _entries[i].get(_CSCORE) + ",\t" + _entries[i].get(_CTIME) + "\n");
	}

    }

    public void generateTable(String filename, int copies) throws Exception {
        int _MAXI = _entries.length;
        int _MAXJ = _CVALUE_COLUMNS.length;
        String[] toks;

	FileWriter wr = new FileWriter(filename);

        _table = new String[_MAXI][_CNAMES.length];
        _MAXJ = _CVALUE_COLUMNS.length;
        for (int i=0; i < _MAXI; i++) {
            toks = Util.split(".", _entries[i].toString());
            _table[i][0] = toks[toks.length-1];
		wr.write(copies + ",\t");
		wr.write(_entries[i].toString());
            for (int j=0; j < _MAXJ; j++) {
                _table[i][j+1] = _nf.format(_entries[i].get(j));
		wr.write(",\t" + _table[i][j+1]);
            }
		wr.write("\n");
        }
	wr.close();
    }
    
    public String name() throws Exception {
        return _CNAME;
    }

    public void addTableModelListener(TableModelListener __listener) {
        if (!_listeners.contains(__listener)) {
            _listeners.add(__listener);
        }
    }

    public void removeTableModelListener(TableModelListener __listener) {
        _listeners.remove(__listener);
    }

    public Class getColumnClass(int __col) {
        return _cellclass;
    }

    public int getColumnCount() {
        return _CVALUE_COLUMNS.length + 1;
    }

    public String getColumnName(int __col) {
        return _CNAMES[__col];
    }

    public int getRowCount() {
        if (_table == null) {
            return 0;
        }
        return _table.length;
    }

    public Object getValueAt(int __row, int __col) {
        return _table[__row][__col];
    }

    public boolean isCellEditable(int __row, int __col) {
        return false;
    }

    public void setValueAt(Object __obj, int __row, int __col)
    { }
    
    public void columnAdded(TableColumnModelEvent __event) 
    { }
    
    public void columnMarginChanged(ChangeEvent __event)
    { }

    public void columnMoved(TableColumnModelEvent __event)
    { }
    
    public void columnRemoved(TableColumnModelEvent __event)
    { }
    
    public void columnSelectionChanged(ListSelectionEvent __event) {
        try {
            int index = __event.getFirstIndex();
        
            if (index == 0) {
                Arrays.sort(_entries);
//                generateTable();
                return;
            }
            Arrays.sort(_entries, new PlayerEntrySorter(index-1));
 //           generateTable();
        } catch (Exception EXC) {
            System.out.println(EXC.getMessage());
            EXC.printStackTrace();
        }
    }

    private class PlayerEntry implements Comparable {
        Class _player;
        String _name;
        double[] _values;

        public PlayerEntry(Class __player) throws Exception {
            _player = __player;
            _name = _player.toString();

		_name = _name.substring(1 + _name.lastIndexOf('.'));

            _values = new double[_CVALUE_COLUMNS.length];
        }
        
        public void set(int __pos, double __val) throws Exception {
            _values[__pos] = __val;
        }

        public double get(int __pos) throws Exception {
            return _values[__pos];
        }
        
        public int compareTo(Object __obj) {
            return toString().compareTo(((PlayerEntry) __obj).toString());
        }

        public boolean equals(Object __obj) {
            if (!(__obj instanceof PlayerEntry)) {
                return false;
            }
            return ((PlayerEntry) __obj).equals(this);
        }

        public String toString() {
            return _name;
        }
    }
    
    private class ClassScorePair implements Comparable {
    
        Class _class;
        double _score;
        
        public ClassScorePair(Class __class, double __score) throws Exception {
            _class = __class;
            _score = __score;
        }
        
        public int compareTo(Object __obj) {
            try {
                double score = ((ClassScorePair) __obj)._score;

                return (_score < score ? -1 : (_score > score ? 1 : 0));
            } catch (Exception EXC) {
                System.out.println(EXC.getMessage());
                EXC.printStackTrace();
                return 0;
            }
        }

        public Class playerClass() throws Exception {
            return _class;
        }

        public double score() throws Exception {
            return score();
        }
    }
    
    private class PlayerEntrySorter implements Comparator {
        
        int _sortindex;
    
        public PlayerEntrySorter(int __sortindex) {
            _sortindex = __sortindex;
        }

        public int compare(Object __obj1, Object __obj2) {
            try {
                double val1 = ((PlayerEntry) __obj1).get(_sortindex);
                double val2 = ((PlayerEntry) __obj2).get(_sortindex);

                return (val1 < val2 ? -1 : (val1 > val2 ? 1 : 0));
            } catch (Exception EXC) {
                System.out.println(EXC.getMessage());
                EXC.printStackTrace();
                return 0;
            }
         }
    }
}
