/**
 * THE ModeratorJournal.java WRITEME...
 */
package com.tootsville.sys.op;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map.Entry;

import org.starhope.appius.except.NotFoundException;
import org.starhope.appius.game.AppiusClaudiusCaecus;
import org.starhope.appius.sql.SQLPeerDatum;
import org.starhope.appius.user.AbstractUser;
import org.starhope.appius.user.Nomenclator;
import org.starhope.appius.util.AppiusConfig;

/**
 * Moderator journal is a one time entry that can be added using an
 * extension command or by any system processes. The only step required
 * is created a new instance. The data provided will be parsed and
 * formatted then stored in the database. Retrieving the data will
 * create all the required information. Potential upgrade is to use a
 * configuration file to format the output when retrieving the entry.
 * Example of this is that in Joshua references to usernames can be
 * returned in the entry as anchor links to a user profile. <h3>DOES NOT
 * WORK. NEVER HAS.</h3>
 * 
 * @author <a href="mailto:twheys@gmail.com@resinteractive.com">Tim
 *         Heys</a>
 */
@Deprecated
public class ModeratorJournal extends SQLPeerDatum {
    /**
     * Generated serialization ID
     */
    private static final long serialVersionUID = -2563726734882518619L;
	
	/**
	 * <pre>
	 * twheys@gmail.com Jan 28, 2010
	 * </pre>
	 * 
	 * TO getJournalByID SELECT from database on ID and build from
	 * result set.
	 * 
	 * @param idToGet the ID of the moderator journal entry to retrieve
	 * @return a Moderator Journal with the ID idToGet
	 * @throws NotFoundException if no journal exists with the ID
	 *             idToGet
	 */
    public static ModeratorJournal getJournalByID (final int idToGet)
    throws NotFoundException {
        Connection con = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try {
            con = AppiusConfig.getDatabaseConnection ();
            st = con
            .prepareStatement ("SELECT * FROM moderatorJournal WHERE ID=?");
            st.setInt (1, idToGet);
            rs = st.executeQuery ();
            rs.next ();
            return new ModeratorJournal (rs);
        } catch (final SQLException e) {
            throw new NotFoundException (String.valueOf (idToGet));
        } finally {
            if (null != rs) {
                try {
                    rs.close ();
                } catch (final SQLException e) { /* No Op */
                }
            }
            if (null != st) {
                try {
                    st.close ();
                } catch (final SQLException e) { /* No Op */
                }
            }
            if (null != con) {
                try {
                    con.close ();
                } catch (final SQLException e) { /* No Op */
                }
            }

        }

    }
	
	/**
	 * User ID of the author
	 * 
	 * @see org.starhope.appius.user.User
	 */
    private int authorID;
    /**
     * Text entered into the entry
     */
    private String entryText;

    /**
     * ID of the journal entry
     */
    private int id;

    /**
     * Refences to users made in the shift journal. This is accomplished
     * by entering an "@username" into the entry.
     */
    private HashMap <Integer, String> references = new HashMap <Integer, String> ();

    /**
     * Timestamp of when the post was created.
     */
    private Timestamp stamp;
	
	/**
	 * <pre>
	 * twheys@gmail.com Jan 28, 2010
	 * </pre>
	 * 
	 * A ModeratorJournal creates an new object of a moderator journal,
	 * parses the entry for references, then
	 * 
	 * @param author WRITEME
	 * @param entry WRITEME
	 */
    public ModeratorJournal (final AbstractUser author,
            final String entry) {
        authorID = author.getUserID ();
        entryText = entry;
        parseReferences ();
        insert ();
    }
	
	/**
	 * <pre>
	 * twheys@gmail.com Jan 28, 2010
	 * </pre>
	 * 
	 * A ModeratorJournal created from a result set.
	 * 
	 * @param rs the result set from a SELECT statment
	 */
    public ModeratorJournal (final ResultSet rs) {
        try {
            set (rs);
        } catch (final SQLException e) {
            AppiusClaudiusCaecus.reportBug (
                    "Unable to instantiate Moderator Journal", e);
        }
    }
	
	/**
	 * <pre>
	 * twheys@gmail.com Jan 28, 2010
	 * </pre>
	 * 
	 * TO checkReferencePossibility try to get a user ID for a userName,
	 * if successful add to references.
	 * 
	 * @param possibleUser the username being checked
	 */
    private void checkReferencePossibility (final String possibleUser) {
        final int possibleID = Nomenclator.getUserIDForLogin (possibleUser);
        if (0 == possibleID) {
            return;
        }
        references.put (Integer.valueOf(possibleID), possibleUser);
    }
	
	/**
	 * Don't use, moderator journals are never updated. Throws fatal
	 * bug.
	 * 
	 * @see org.starhope.appius.sql.SQLPeerDatum#flush()
	 */
    @Override
    public void flush () {
        AppiusClaudiusCaecus
        .fatalBug ("Attempting to change an already set moderator journal entry");
    }

    /**
     * @return the authorID
     */
    public int getAuthorID () {
        return authorID;
    }

    /**
     * @see org.starhope.appius.sql.SQLPeerDatum#getCacheUniqueID()
     */
    @Override
    protected String getCacheUniqueID () {
        return "ModeratorJournal#" + id;

    }

    /**
     * @return the entryText
     */
    public String getEntryText () {
        return entryText;
    }

    /**
     * @return the id
     */
    public int getId () {
        return id;
    }

    /**
     * @return the references
     */
    public HashMap <Integer, String> getReferences () {
        return references;
    }

    /**
     * @return the stamp
     */
    public Timestamp getStamp () {
        return stamp;
    }
	
	/**
	 * <pre>
	 * twheys@gmail.com Jan 28, 2010
	 * </pre>
	 * 
	 * TO getReferencesForThis SELECT references with the journalID that
	 * matches the ID of this journal entry.
	 */
    private void initReferencesForThis () {
        Connection con = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try {
            con = AppiusConfig.getDatabaseConnection ();
            st = con
            .prepareStatement ("SELECT * FROM moderatorJournalReference WHERE ID=?");
            st.setInt (1, id);
            rs = st.executeQuery ();
            setReferences (rs);
        } catch (final SQLException e) {
            AppiusClaudiusCaecus
            .reportBug (
                    "Couldn't get any references, maybe there are none?",
                    e);
        } finally {
            if (null != rs) {
                try {
                    rs.close ();
                } catch (final SQLException e) { /* No Op */
                }
            }
            if (null != st) {
                try {
                    st.close ();
                } catch (final SQLException e) { /* No Op */
                }
            }
            if (null != con) {
                try {
                    con.close ();
                } catch (final SQLException e) { /* No Op */
                }
            }

        }
    }
	
	/**
	 * <pre>
	 * twheys@gmail.com Jan 28, 2010
	 * </pre>
	 * 
	 * TO insert insert into moderatorJournal with the members of this
	 * instance.
	 */
    private void insert () {
        Connection con = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try {
            con = AppiusConfig.getDatabaseConnection ();
            st = con
            .prepareStatement (
                    "INSERT INTO moderatorJournal (author, journalEntry, stamp) VALUES (?,?,NOW ())",
                    Statement.RETURN_GENERATED_KEYS);
            st.setInt (1, authorID);
            st.setString (2, entryText);
            st.execute ();
            rs = st.getGeneratedKeys ();
            rs.next ();
            id = rs.getInt ("ID");
            stamp = rs.getTimestamp ("stamp");
            insertReferences ();
        } catch (final SQLException e) {
            AppiusClaudiusCaecus.reportBug (
                    "Couldn't create journal entry", e);
        } finally {
            if (null != rs) {
                try {
                    rs.close ();
                } catch (final SQLException e) { /* No Op */
                }
            }
            if (null != st) {
                try {
                    st.close ();
                } catch (final SQLException e) { /* No Op */
                }
            }
            if (null != con) {
                try {
                    con.close ();
                } catch (final SQLException e) { /* No Op */
                }
            }
        }
    }
	
	/**
	 * <pre>
	 * twheys@gmail.com Jan 28, 2010
	 * </pre>
	 * 
	 * TO insertReferences WRITEME...
	 * 
	 * @throws SQLException WRITEME
	 */
    private void insertReferences () throws SQLException {
        Connection con = null;
        PreparedStatement st = null;
        con = AppiusConfig.getDatabaseConnection ();
        try {
            st = con
            .prepareStatement ("INSERT INTO moderatorJournalReference (journalID, userReferenceName, userReference) VALUES (?,?,?)");
            st.setInt (1, id);
            for (final Entry <Integer, String> reference : references
                    .entrySet ()) {
                st.setString (2, reference.getValue ());
                st.setInt (3, reference.getKey ().intValue ());
                st.execute ();
            }
        } finally {
            if (null != st) {
                try {
                    st.close ();
                } catch (final SQLException e) { /* No Op */
                }
            }
            if (null != con) {
                try {
                    con.close ();
                } catch (final SQLException e) { /* No Op */
                }
            }
        }
    }
	
	/**
	 * <pre>
	 * twheys@gmail.com Jan 28, 2010
	 * </pre>
	 * 
	 * TO parseReferences scan through the entry looking for "@username"
	 * entries.
	 */
    private void parseReferences () {
        final String splitText[] = entryText.split (" ");
        for (final String word : splitText) {
            if ('@' == word.charAt (0)) {
                checkReferencePossibility (word.substring (1));
            }
        }
    }

    /**
     * @see org.starhope.appius.sql.SQLPeerDatum#set(java.sql.ResultSet)
     */
    @Override
    protected void set (final ResultSet rs) throws SQLException {
        id = rs.getInt ("ID");
        authorID = rs.getInt ("author");
        stamp = rs.getTimestamp ("stamp");
        entryText = rs.getString ("journalEntry");
        initReferencesForThis ();
    }

    /**
     * @param newAuthor the authorID to set
     */
    public void setAuthorID (final int newAuthor) {
        authorID = newAuthor;
    }

    /**
     * @param newEntry the entryText to set
     */
    public void setEntryText (final String newEntry) {
        entryText = newEntry;
    }

    /**
     * @param newID the id to set
     */
    public void setId (final int newID) {
        id = newID;
    }

    /**
     * @param newReferences the references to set
     */
    public void setReferences (
            final HashMap <Integer, String> newReferences) {
        references = newReferences;
    }
	
	/**
	 * <pre>
	 * twheys@gmail.com Jan 28, 2010
	 * </pre>
	 * 
	 * TO set_References WRITEME...
	 * 
	 * @param rs WRITEME
	 * @throws SQLException WRITEME
	 */
    protected void setReferences (final ResultSet rs)
    throws SQLException {
        while (rs.next ()) {
            final int userReferenceID = rs.getInt ("userReferenceID");
            final String userReferenceName = rs
            .getString ("userReferenceName");
            references.put (Integer.valueOf (userReferenceID),
                    userReferenceName);
        }
    }

    /**
     * @param newStamp the stamp to set
     */
    public void setStamp (final Timestamp newStamp) {
        stamp = newStamp;
    }
}
