

package gov.va.med.cds.properties;


import gov.va.med.cds.util.CipherUtilities;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Properties;

import javax.crypto.spec.SecretKeySpec;


public class PropertiesManager
{
    
    public static final String PROPERTIES_FILE_PATH_PROPERTY = "cds.run.properties.path";
    public static final String PROPERTIES_ENCRYPTION_SWITCH = "cds.encrypt.password.properties";
    public static final String PROPERTIES_KEYSTORE_PSWD = "cds.keystore.password";

    protected Properties loadPropertiesFromPropertiesFile( String propertiesFilePath )
        throws FileNotFoundException,
            IOException
    {
    	InputStream propInputStream = null;
        Properties fileProps = new Properties();

    	try
    	{
	        propInputStream = new FileInputStream( propertiesFilePath );	        
	        fileProps.load( propInputStream );
	        propInputStream.close();
    	}
    	finally
    	{
            if ( propInputStream != null )
            {
            	propInputStream.close();
            }
    	}
    	
        return fileProps;
    }


    protected String getKeyStorePasswordFromSystemProperties( )
    {
        String keyStorePassword = System.getProperty( PROPERTIES_KEYSTORE_PSWD );
        return keyStorePassword;
    }


    protected String getEncryptSwitchFromSystemProperties( )
    {
        String encrypt = System.getProperty( PROPERTIES_ENCRYPTION_SWITCH );
        return encrypt;
    }


    protected String getPropertiesFilePathFromSystemProperties( )
    {
        String propertiesFilePath = System.getProperty( PROPERTIES_FILE_PATH_PROPERTY );
        return propertiesFilePath;
    }


    protected void updateSystemProperties( Properties fileProps )
    {
        Properties systemProps = System.getProperties();
        systemProps.putAll( fileProps );
        System.setProperties( systemProps );
    }


    protected void encryptProperties( SecretKeySpec savedKey, String propertiesFilePath, Properties propsToBeSaved )
        throws IOException
    {
    	FileOutputStream fos = null;
    	
        Enumeration<?> e = propsToBeSaved.propertyNames();
        while ( e.hasMoreElements() )
        {
            String propKey = ( String )e.nextElement();
            if ( propKey.endsWith( ".password" ) )
            {
                String propValue = propsToBeSaved.getProperty( propKey );
                //if property has been already encrypted, skip it
                if (! CipherUtilities.isEncrypted( propValue ) ) 
                {
                    propsToBeSaved.setProperty( propKey, CipherUtilities.encrypt( savedKey, propValue ) );
                }
            }
        }

        fos = new java.io.FileOutputStream( new File( propertiesFilePath ) );
        try
        {
            propsToBeSaved.store( fos, "File encrypted" );
            fos.close();
        }
        finally
        {
            if ( fos != null )
            {
            	fos.close();
            }
        }

    }


    protected Properties decryptProperties( SecretKeySpec savedKey, String keyStoreFileLocation, String keyStorePassword, Properties fileProps )
        throws IOException
    {
        Enumeration<?> e = fileProps.propertyNames();
        while ( e.hasMoreElements() )
        {
            String propKey = ( String )e.nextElement();
            if ( propKey.endsWith( ".password" ) )
            {
                String propValue = fileProps.getProperty( propKey );
                if ( propValue.startsWith( CipherUtilities.ENCRYPTED_PREFIX ) )
                {
                    //property is encrypted - make sure CipherUtilities is configured 
                    //if is has not already been configured and if anything is
                    //missing for configuration a runtime exception will be thrown
                    if ( savedKey == null )
                    {
                        savedKey = configureKeyStore( keyStoreFileLocation, keyStorePassword );
                    }
                    fileProps.setProperty( propKey, decrypt( savedKey, propValue ) );
                }
            }
        }
        return fileProps;
    }


    protected String decrypt( SecretKeySpec savedKey, String propValue )
    {
        return CipherUtilities.decrypt( savedKey, propValue );
    }


    protected SecretKeySpec configureKeyStore( String keyStoreFileLocation, String keyStorePassword )
        throws IOException
    {
        return CipherUtilities.configureKeyStore( keyStoreFileLocation, keyStorePassword );
    }

}
