/*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software
 * License version 1.1, a copy of which has been included with this
 * distribution in the LICENSE.txt file.  */
package org.apache.log4j.chainsaw;

import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.swing.table.AbstractTableModel;
import org.apache.log4j.Priority;
import org.apache.log4j.Logger;

/**
 * Represents a list of <code>EventDetails</code> objects that are sorted on
 * logging time. Methods are provided to filter the events that are visible.
 *
 * @author <a href="mailto:oliver@puppycrawl.com">Oliver Burn</a>
 */
class MyTableModel
    extends AbstractTableModel
{

    /** used to log messages **/
    private static final Logger LOG = Logger.getLogger(MyTableModel.class);

    /** use the compare logging events **/
    private static final Comparator MY_COMP = new Comparator()
    {
        /** @see Comparator **/
        public int compare(Object aObj1, Object aObj2) {
            if ((aObj1 == null) && (aObj2 == null)) {
                return 0; // treat as equal
            } else if (aObj1 == null) {
                return -1; // null less than everything
            } else if (aObj2 == null) {
                return 1; // think about it. :->
            }

            // will assume only have LoggingEvent
            final EventDetails le1 = (EventDetails) aObj1;
            final EventDetails le2 = (EventDetails) aObj2;

            if (le1.getTimeStamp() < le2.getTimeStamp()) {
                return 1;
            }
            // assume not two events are logged at exactly the same time
            return -1;
        }
        };

    /**
     * Helper that actually processes incoming events.
     * @author <a href="mailto:oliver@puppycrawl.com">Oliver Burn</a>
     */
    private class Processor
        implements Runnable
    {
        /** loops getting the events **/
        public void run() {
            while (true) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // ignore
                }

                synchronized (mLock) {
                    if (mPaused) {
                        continue;
                    }

                    boolean toHead = true; // were events added to head
                    boolean needUpdate = false;
                    final Iterator it = mPendingEvents.iterator();
                    while (it.hasNext()) {
                        final EventDetails event = (EventDetails) it.next();
                        mAllEvents.add(event);
                        toHead = toHead && (event == mAllEvents.first());
                        needUpdate = needUpdate || matchFilter(event);
                    }
                    mPendingEvents.clear();

                    if (needUpdate) {
                        updateFilteredEvents(toHead);
                    }
                }
            }

        }
    }


    /** names of the columns in the table **/
    private static final String[] COL_NAMES = {
        "Time", "Priority", "Trace", "Category", "NDC", "Message"};

    /** definition of an empty list **/
    private static final EventDetails[] EMPTY_LIST =  new EventDetails[] {};

    /** used to format dates **/
    private static final DateFormat DATE_FORMATTER =
        DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM);

    /** the lock to control access **/
    private final Object mLock = new Object();
    /** set of all logged events - not filtered **/
    private final SortedSet mAllEvents = new TreeSet(MY_COMP);
    /** events that are visible after filtering **/
    private EventDetails[] mFilteredEvents = EMPTY_LIST;
    /** list of events that are buffered for processing **/
    private final List mPendingEvents = new ArrayList();
    /** indicates whether event collection is paused to the UI **/
    private boolean mPaused = false;

    /** filter for the thread **/
    private String mThreadFilter = "";
    /** filter for the message **/
    private String mMessageFilter = "";
    /** filter for the NDC **/
    private String mNDCFilter = "";
    /** filter for the category **/
    private String mCategoryFilter = "";
    /** filter for the priority **/
    private Priority mPriorityFilter = Priority.DEBUG;


    /**
     * Creates a new <code>MyTableModel</code> instance.
     *
     */
    MyTableModel() {
        final Thread t = new Thread(new Processor());
        t.setDaemon(true);
        t.start();
    }


    ////////////////////////////////////////////////////////////////////////////
    // Table Methods
    ////////////////////////////////////////////////////////////////////////////

    /** @see javax.swing.table.TableModel **/
    public int getRowCount() {
        synchronized (mLock) {
            return mFilteredEvents.length;
        }
    }

    /** @see javax.swing.table.TableModel **/
    public int getColumnCount() {
        // does not need to be synchronized
        return COL_NAMES.length;
    }

    /** @see javax.swing.table.TableModel **/
    public String getColumnName(int aCol) {
        // does not need to be synchronized
        return COL_NAMES[aCol];
    }

    /** @see javax.swing.table.TableModel **/
    public Class getColumnClass(int aCol) {
        // does not need to be synchronized
        return (aCol == 2) ? Boolean.class : Object.class;
    }

    /** @see javax.swing.table.TableModel **/
    public Object getValueAt(int aRow, int aCol) {
        synchronized (mLock) {
            final EventDetails event = mFilteredEvents[aRow];

            if (aCol == 0) {
                return DATE_FORMATTER.format(new Date(event.getTimeStamp()));
            } else if (aCol == 1) {
                return event.getPriority();
            } else if (aCol == 2) {
                return (event.getThrowableStrRep() == null)
                    ? Boolean.FALSE : Boolean.TRUE;
            } else if (aCol == 3) {
                return event.getCategoryName();
            } else if (aCol == 4) {
                return event.getNDC();
            }
            return event.getMessage();
        }
    }

    ////////////////////////////////////////////////////////////////////////////
    // Public Methods
    ////////////////////////////////////////////////////////////////////////////

    /**
     * Sets the priority to filter events on. Only events of equal or higher
     * property are now displayed.
     *
     * @param aPriority the priority to filter on
     */
    public void setPriorityFilter(Priority aPriority) {
        synchronized (mLock) {
            mPriorityFilter = aPriority;
            updateFilteredEvents(false);
        }
    }

    /**
     * Set the filter for the thread field.
     *
     * @param aStr the string to match
     */
    public void setThreadFilter(String aStr) {
        synchronized (mLock) {
            mThreadFilter = aStr.trim();
            updateFilteredEvents(false);
        }
    }

    /**
     * Set the filter for the message field.
     *
     * @param aStr the string to match
     */
    public void setMessageFilter(String aStr) {
        synchronized (mLock) {
            mMessageFilter = aStr.trim();
            updateFilteredEvents(false);
        }
    }

    /**
     * Set the filter for the NDC field.
     *
     * @param aStr the string to match
     */
    public void setNDCFilter(String aStr) {
        synchronized (mLock) {
            mNDCFilter = aStr.trim();
            updateFilteredEvents(false);
        }
    }

    /**
     * Set the filter for the category field.
     *
     * @param aStr the string to match
     */
    public void setCategoryFilter(String aStr) {
        synchronized (mLock) {
            mCategoryFilter = aStr.trim();
            updateFilteredEvents(false);
        }
    }

    /**
     * Add an event to the list.
     *
     * @param aEvent a <code>EventDetails</code> value
     */
    public void addEvent(EventDetails aEvent) {
        synchronized (mLock) {
            mPendingEvents.add(aEvent);
        }
    }

    /**
     * Clear the list of all events.
     */
    public void clear() {
        synchronized (mLock) {
            mAllEvents.clear();
            mFilteredEvents = new EventDetails[0];
            mPendingEvents.clear();
            fireTableDataChanged();
        }
    }

    /** Toggle whether collecting events **/
    public void toggle() {
        synchronized (mLock) {
            mPaused = !mPaused;
        }
    }

    /** @return whether currently paused collecting events **/
    public boolean isPaused() {
        synchronized (mLock) {
            return mPaused;
        }
    }

    /**
     * Get the throwable information at a specified row in the filtered events.
     *
     * @param aRow the row index of the event
     * @return the throwable information
     */
    public EventDetails getEventDetails(int aRow) {
        synchronized (mLock) {
            return mFilteredEvents[aRow];
        }
    }

    ////////////////////////////////////////////////////////////////////////////
    // Private methods
    ////////////////////////////////////////////////////////////////////////////

    /**
     * Update the filtered events data structure.
     * @param aInsertedToFront indicates whether events were added to front of
     *        the events. If true, then the current first event must still exist
     *        in the list after the filter is applied.
     */
    private void updateFilteredEvents(boolean aInsertedToFront) {
        final long start = System.currentTimeMillis();
        final List filtered = new ArrayList();
        final int size = mAllEvents.size();
        final Iterator it = mAllEvents.iterator();

        while (it.hasNext()) {
            final EventDetails event = (EventDetails) it.next();
            if (matchFilter(event)) {
                filtered.add(event);
            }
        }

        final EventDetails lastFirst = (mFilteredEvents.length == 0)
            ? null
            : mFilteredEvents[0];
        mFilteredEvents = (EventDetails[]) filtered.toArray(EMPTY_LIST);

        if (aInsertedToFront && (lastFirst != null)) {
            final int index = filtered.indexOf(lastFirst);
            if (index < 1) {
                LOG.warn("In strange state");
                fireTableDataChanged();
            } else {
                fireTableRowsInserted(0, index - 1);
            }
        } else {
            fireTableDataChanged();
        }

        final long end = System.currentTimeMillis();
        LOG.debug("Total time [ms]: " + (end - start)
                  + " in update, size: " + size);
    }

    /**
     * Returns whether an event matches the filters.
     *
     * @param aEvent the event to check for a match
     * @return whether the event matches
     */
    private boolean matchFilter(EventDetails aEvent) {
        if (aEvent.getPriority().isGreaterOrEqual(mPriorityFilter) &&
            (aEvent.getThreadName().indexOf(mThreadFilter) >= 0) &&
            (aEvent.getCategoryName().indexOf(mCategoryFilter) >= 0) &&
            ((mNDCFilter.length() == 0) ||
             ((aEvent.getNDC() != null) &&
              (aEvent.getNDC().indexOf(mNDCFilter) >= 0))))
        {
            final String rm = aEvent.getMessage();
            if (rm == null) {
                // only match if we have not filtering in place
                return (mMessageFilter.length() == 0);
            } else {
                return (rm.indexOf(mMessageFilter) >= 0);
            }
        }

        return false; // by default not match
    }
}
