/*
 * AddressBookConfiguration.java
 *
 * Copyright 2011 John W Dawson
 *
 * This code is distributed under the terms of the GNU General Public License, version 3
 *
 * This class handles the program's configuration data, which is represented externally 
 * by an XML file and internally as a DOM document
 */

import org.jdom2.*;
import org.jdom2.output.*;
import org.jdom2.input.*;
import org.jdom2.filter.*;
import java.io.*;
import javax.swing.*;
import java.util.*;
import java.io.*;
import java.util.logging.*;
public class AddressBookConfiguration extends ConfigurationRecord
{
  static Logger log = Logger.getLogger ("LdapAddressBook");
  private Document document;
  private File configurationDir = new File (System.getProperty ("user.home") + System.getProperty ("file.separator") +
                                              ".LdapAddressBook");
  private File configurationFile = new File (configurationDir, "config.xml");
  private File trustStoreFile = new File (configurationDir, "cacerts");
  private Boolean defaultConfiguration = false;
  private MessageLine messageLine;
  private LdapConnection connection;
  private ExtensionSelector extensionSelector;
  private EditPanel editPanel;
  
  public AddressBookConfiguration (MessageLine messageLine, LdapConnection connection)
  throws JDOMException, IOException
  {
    
    this.messageLine = messageLine;
    this.connection = connection;
    
    SAXBuilder builder = new SAXBuilder ();  
    
    // Check if file exists
    if (configurationFile.exists ())
    {
      // If so load contents into document
      this.document = builder.build (configurationFile); 
      setBase (this.document.getRootElement ());  
      
        
    }
    else
    {
      // Load default configuration bundled in JAR file
      this.document = builder.build (getClass().getResource ("/config/default.xml")); 
      setBase (this.document.getRootElement ());  
      defaultConfiguration = true;
      
    }
    
    // Set up local trust store if required
    setTrustStore ();
  }
  
  private void setTrustStore ()
  {
    try
    {
      // Check if local trust store exists in user directory
      if (!trustStoreFile.exists ())
      {
        // If not check if file included in JAR
        InputStream trustStoreStream = getClass().getResourceAsStream ("/ssl/cacerts");
        if (trustStoreStream == null)
        {
          return;
        }
        
        // Copy file to user's directory
        FileOutputStream out = new FileOutputStream (trustStoreFile);
        byte [] buff = new byte [1024];
        int numRead;
        while ((numRead = trustStoreStream.read (buff)) > 0)
        {
          out.write (buff, 0, numRead);
        }
        trustStoreStream.close ();
        out.close ();
      }
      
      // Conigure java to use local trust store
      System.setProperty ("javax.net.ssl.trustStore", trustStoreFile.getPath());
    }
    catch (IOException e)
    {
      System.out.println (e.getMessage());
      e.printStackTrace();
    }
  }      
          
  public void initialise (JFrame mainWindow, EditPanel editPanel, ExtensionSelector extensionSelector)
  {
    this.editPanel = editPanel;
    this.extensionSelector = extensionSelector;
    
    // Check if initial program run with default configuration and password use is optional or required
    if (defaultConfiguration && !getElementValue ("usepassword").equals ("none"))
    {
      // Prompt user to set password if required
      new PasswordConfigurationForm (this, mainWindow); 
    }
    else
    {
      // Check if password has been set
      String passwordHash = getElementValue ("addressbookpassword");
      if (passwordHash != null)
      {
        // If so prompt user to enter password
        new PasswordEntryForm (this, mainWindow, passwordHash);
      } 
      else
      {
        // Otherwise proceed with initialisation using default password for encryption
        passwordSet ("");
      }
    }
  }

  public void passwordSet (String password)
  { 
    // Create an encryptor/decryptor with a key derived from the password entered by user, or
    // the default password
    encryptorDecryptor = new EncryptorDecryptor (password);  
    
    // Check if LDAP server has been configured
    String ldapServer = getElementValue ("ldapserver");
    if (ldapServer == null)
    {
      messageLine.setPersistentText ("No LDAP directory configured");
    }
    else
    {
      // Connect to LDAP server
      connection.connect ();
    }
    
    // Initialise extension selector      
    extensionSelector.initialise (this, editPanel);
  }
  
  
  
  public void save ()
  {
    try
    {
      // Output the document to the file
      XMLOutputter outputter = new XMLOutputter (Format.getPrettyFormat());
      outputter.output (this.document, new FileOutputStream (configurationFile));
      messageLine.setTransientText ("Configuration data saved");
    }
    catch (IOException e)
    {
      JOptionPane.showMessageDialog (messageLine.getParent(), "Failed to save configuration data", 
                                     "I/O Failure", JOptionPane.ERROR_MESSAGE);
    }
      
  }
}