/*
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 * (the "License"); you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
 * 
 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
 * language governing rights and limitations under the License.
 * 
 * The Original Code is the Venice Web Communities System.
 * 
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@ricochet.com>,
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 * Copyright (C) 2001-2004 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 * 
 * Contributor(s): 
 */
package com.silverwrist.venice.core.impl;

import java.sql.*;
import java.util.*;
import org.apache.log4j.*;
import com.silverwrist.util.*;
import com.silverwrist.venice.core.*;
import com.silverwrist.venice.core.internals.*;
import com.silverwrist.venice.db.*;
import com.silverwrist.venice.except.*;
import com.silverwrist.venice.util.*;

class UserProfileImpl implements UserProfile
{
  /*--------------------------------------------------------------------------------
   * Static data members
   *--------------------------------------------------------------------------------
   */

  private static Category logger = Category.getInstance(UserProfileImpl.class);

  /*--------------------------------------------------------------------------------
   * Attributes
   *--------------------------------------------------------------------------------
   */

  private EnvUser env;                   // the user environment
  private int uid;                       // user ID
  private String username;               // user name
  private String given_name;             // given name ("first name")
  private String family_name;            // family name ("last name")
  private char middle_initial;           // middle initial (natch)
  private String prefix;                 // prefix (Mr., Ms., Prof., Dr., etc.)
  private String suffix;                 // suffix (Jr., III, etc.)
  private String company;                // company name
  private String addr1;                  // address line 1
  private String addr2;                  // address line 2
  private String locality;               // locality ("city")
  private String region;                 // region ("state")
  private String postal_code;            // postal code ("ZIP code")
  private String country;                // 2-character ISO 3166 country code
  private String phone;                  // voice phone number
  private String fax;                    // facsimile (fax) number
  private String mobile;                 // mobile phone (cellphone) number
  private String email;                  // email address
  private String photo_url;              // URL of user photo
  private String url;                    // URL of user's homepage
  private String descr;                  // user's self-description
  private java.util.Date created;        // date created
  private java.util.Date last_login;     // date of last login
  private java.util.Date last_update;    // date of last update
  private String real_email;             // real email address
  private boolean is_anon;               // is this the anonymous account?

  /*--------------------------------------------------------------------------------
   * Constructors
   *--------------------------------------------------------------------------------
   */

  UserProfileImpl(EnvUser env, Connection conn, String username) throws DataException, SQLException
  {
    if (logger.isDebugEnabled())
      logger.debug("load UserProfileImpl by name: " + username);
    this.env = env;

    Statement stmt = null;
    int contact_id = -1;

    try
    { // first retrieve from the users table
      stmt = conn.createStatement();
      StringBuffer sql = new StringBuffer("SELECT uid, username, contactid, created, lastaccess, description, "
					  + "is_anon FROM users WHERE username = '");
      sql.append(SQLUtil.encodeString(username)).append("';");
      ResultSet rs = stmt.executeQuery(sql.toString());
      if (!(rs.next()))
      { // we didn't find the user
	logger.error("unable to find user with username '" + username + "'");
	throw new DataException("User '" + username + "' not found.");

      } // end if

      // load the "elementary" fields
      this.uid = rs.getInt(1);
      this.username = rs.getString(2);
      contact_id = rs.getInt(3);
      created = SQLUtil.getFullDateTime(rs,4);
      last_login = SQLUtil.getFullDateTime(rs,5);
      descr = rs.getString(6);
      is_anon = rs.getBoolean(7);

    } // end try
    finally
    { // shut down the statement to conserve resources
      SQLUtil.shutdown(stmt);

    } // end finally

    loadContact(conn,contact_id);

  } // end constructor

  UserProfileImpl(EnvUser env, Connection conn, int uid) throws DataException, SQLException
  {
    if (logger.isDebugEnabled())
      logger.debug("load UserProfileImpl by UID: " + uid);
    this.env = env;

    Statement stmt = null;
    int contact_id = -1;

    try
    { // first retrieve from the users table
      stmt = conn.createStatement();
      StringBuffer sql = new StringBuffer("SELECT uid, username, contactid, created, lastaccess, description, "
					  + "is_anon FROM users WHERE uid = ");
      sql.append(uid).append(';');
      ResultSet rs = stmt.executeQuery(sql.toString());
      if (!(rs.next()))
      { // we didn't find user
	logger.error("unable to find user with uid " + uid);
	throw new DataException("User #" + String.valueOf(uid) + " not found.");

      } // end if

      // load the "elementary" fields
      this.uid = rs.getInt(1);
      this.username = rs.getString(2);
      contact_id = rs.getInt(3);
      created = SQLUtil.getFullDateTime(rs,4);
      last_login = SQLUtil.getFullDateTime(rs,5);
      descr = rs.getString(6);
      is_anon = rs.getBoolean(7);

    } // end try
    finally
    { // shut down the statement to conserve resources
      SQLUtil.shutdown(stmt);

    } // end finally

    loadContact(conn,contact_id);
    
  } // end constructor

  /*--------------------------------------------------------------------------------
   * Internal functions
   *--------------------------------------------------------------------------------
   */

  private final void loadContact(Connection conn, int contact_id) throws SQLException
  {
    if (logger.isDebugEnabled())
      logger.debug("loadContact for contact ID " + contact_id);
    boolean override = env.testPermission(EnvUser.PERM_SEEHIDDENCONTACTINFO);

    Statement stmt = null;

    try
    { // look up the contact information
      stmt = conn.createStatement();
      StringBuffer sql = new StringBuffer("SELECT * FROM contacts WHERE contactid = ");
      sql.append(contact_id).append(';');

      ResultSet rs = stmt.executeQuery(sql.toString());
      if (rs.next())
      { // load all the record data
	boolean me_anon = env.isAnonymous();
	given_name = rs.getString("given_name");
	family_name = rs.getString("family_name");
	String blort = rs.getString("middle_init");
	if ((blort==null) || (blort.length()<1))
	  middle_initial = ' ';
	else
	  middle_initial = blort.charAt(0);
	prefix = rs.getString("prefix");
	suffix = rs.getString("suffix");
	company = rs.getString("company");
	if (!override && (me_anon || rs.getBoolean("pvt_addr")))
	{ // enforce address privacy
	  addr1 = null;
	  addr2 = null;

	} // end if
	else
	{ // load the address strings
	  addr1 = rs.getString("addr1");
	  addr2 = rs.getString("addr2");

	} // end else

	locality = rs.getString("locality");
	region = rs.getString("region");
	postal_code = rs.getString("pcode");
	country = rs.getString("country");
	if (!override && (me_anon || rs.getBoolean("pvt_phone")))
	{ // enforce phone privacy
	  phone = null;
	  mobile = null;

	} // end if
	else
	{ // load the phone strings
	  phone = rs.getString("phone");
	  mobile = rs.getString("mobile");

	} // end else

	if (!override && (me_anon || rs.getBoolean("pvt_fax")))
	  fax = null;
	else
	  fax = rs.getString("fax");

	real_email = rs.getString("email");
	if (!override && (me_anon || rs.getBoolean("pvt_email")))
	  email = null;
	else
	  email = real_email;

	photo_url = rs.getString("photo_url");
	url = rs.getString("url");
	last_update = SQLUtil.getFullDateTime(rs,"lastupdate");

      } // end if
      else
      { // no contact ID - just default all the data
	given_name = null;
	family_name = null;
	middle_initial = ' ';
	prefix = null;
	suffix = null;
	company = null;
	addr1 = null;
	addr2 = null;
	locality = null;
	region = null;
	postal_code = null;
	country = null;
	phone = null;
	fax = null;
	mobile = null;
	email = null;
	photo_url = null;
	url = null;
	last_update = null;
	real_email = null;
	
      } // end else

    } // end try
    finally
    { // shut down statement to conserve resources
      SQLUtil.shutdown(stmt);

    } // end finally

  } // end loadContact

  /*--------------------------------------------------------------------------------
   * External operations
   *--------------------------------------------------------------------------------
   */

  public int getUID()
  {
    return uid;

  } // end getUID

  public String getUserName()
  {
    return username;

  } // end getUserName

  public String getGivenName()
  {
    return given_name;

  } // end getGivenName

  public String getFamilyName()
  {
    return family_name;

  } // end getFamilyName

  public char getMiddleInitial()
  {
    return middle_initial;

  } // end getMiddleInitial

  public String getNamePrefix()
  {
    return prefix;

  } // end getNamePrefix

  public String getNameSuffix()
  {
    return suffix;

  } // end getNameSuffix

  public String getCompany()
  {
    return company;

  } // end getCompany

  public String getAddressLine1()
  {
    return addr1;

  } // end getAddressLine1

  public String getAddressLine2()
  {
    return addr2;

  } // end getAddressLine2

  public String getLocality()
  {
    return locality;

  } // end getLocality

  public String getRegion()
  {
    return region;

  } // end getRegion

  public String getPostalCode()
  {
    return postal_code;

  } // end getPostalCode

  public String getCountry()
  {
    return country;

  } // end getCountry

  public String getFullCountry()
  {
    Country c = International.get().getCountryForCode(country);
    return ((c==null) ? null : c.getName());

  } // end getFullCountry

  public String getPhone()
  {
    return phone;

  } // end getPhone

  public String getFax()
  {
    return fax;

  } // end getFax

  public String getMobile()
  {
    return mobile;

  } // end getMobile

  public String getEmail()
  {
    return email;

  } // end getEmail

  public String getPhotoURL()
  {
    return photo_url;

  } // end getPhotoURL

  public String getURL()
  {
    return url;

  } // end getURL
 
  public java.util.Date getCreateDate()
  {
    return created;

  } // end getCreateDate

  public java.util.Date getLastLoginDate()
  {
    return last_login;

  } // end getLastLoginDate

  public java.util.Date getLastUpdate()
  {
    return last_update;

  } // end getLastUpdate

  public String getDescription()
  {
    return descr;

  } // end getDescription

  public boolean isAnonymous()
  {
    return is_anon;

  } // end isAnonymous

  public VCard getVCard()
  {
    BuildVCard bvc = new BuildVCard();
    bvc.setFamilyName(family_name);
    bvc.setGivenName(given_name);
    bvc.setMiddleName(new String(new char[] { middle_initial }).trim());
    bvc.setPrefix(prefix);
    bvc.setSuffix(suffix);
    bvc.setNickname(username);
    bvc.setOrganizationName(company);
    bvc.setNote(descr);
    bvc.setURL(url);

    // add the address to the VCard
    BuildVCardAddress baddr = new BuildVCardAddress();
    baddr.setWorkAddress(true);
    baddr.setPreferred(true);
    if (!StringUtil.isStringEmpty(addr1))
    { // save off address
      if (!StringUtil.isStringEmpty(addr2))
      { // set extension, then street
	baddr.setExtension(addr1);
	baddr.setStreet(addr2);

      } // end if
      else // set the street address
	baddr.setStreet(addr1);

    } // end if

    baddr.setLocality(locality);
    baddr.setRegion(region);
    baddr.setPostalCode(postal_code);
    baddr.setCountry(country);
    bvc.addAddress(baddr.create());

    // Add phone number.
    BuildVCardPhone bphone = new BuildVCardPhone();
    if (!StringUtil.isStringEmpty(phone))
    { // set attributes and number
      bphone.setWorkPhone(true);
      bphone.setVoicePhone(true);
      bphone.setNumber(phone);
      bvc.addPhone(bphone.create());
      bphone.reset();

    } // end if

    // Add fax number.
    if (!StringUtil.isStringEmpty(fax))
    { // set attributes and number
      bphone.setWorkPhone(true);
      bphone.setFax(true);
      bphone.setNumber(fax);
      bvc.addPhone(bphone.create());
      bphone.reset();
      
    } // end if

    // Add mobile number.
    if (!StringUtil.isStringEmpty(mobile))
    { // set attributes and number
      bphone.setCellPhone(true);
      bphone.setPCSPhone(true);
      bphone.setNumber(mobile);
      bvc.addPhone(bphone.create());

    } // end if

    // Add E-mail address.
    if (!StringUtil.isStringEmpty(email))
    { // set attributes and address
      BuildVCardEmail bemail = new BuildVCardEmail();
      bemail.setWorkEmail(true);
      bemail.setInternetEmail(true);
      bemail.setPreferred(true);
      bemail.setAddress(email);
      bvc.addEmailAddress(bemail.create());

    } // end if

    return bvc.create();

  } // end getVCard

  public boolean canSendQuickEmail()
  {
    return !is_anon && !(env.isAnonymous());

  } // end canSendQuickEmail

  public void sendQuickEmail(String subject, String text) throws AccessError, DataException, EmailException
  {
    if (logger.isDebugEnabled())
      logger.debug("Send Quick E-Mail (from uid " + env.getUserID() + " to uid " + uid + ")");

    if (env.isAnonymous())
    { // we can't send quick emails if we're anonymous!
      logger.error("sending user is not logged in.");
      throw new AccessError("You must be logged in to send a quick E-mail message.");

    } // end if

    if (is_anon)
    { // we can't send quick emails to the anonymous user
      logger.error("target user is the anonymous user");
      throw new AccessError("You cannot send E-mail to the anonymous user.");

    } // end if

    // create the emailer object, fill it in, and send it
    MailSend msend = new PersonalMailSend(env.getMailSender(),env.getGlobalSite(),env.getUserProps());
    msend.addRecipient(MailSend.RECIP_TO,real_email);
    msend.setSubject(subject);
    msend.setText(text + "\n");
    msend.send();

  } // end sendQuickEmail

} // end class UserProfileImpl
