

package gov.va.med.cds.filter;


import gov.va.med.cds.clinicaldata.FilterMetaData;
import gov.va.med.cds.clinicaldata.FilterMetaDataInterface;
import gov.va.med.cds.exception.ErrorCodeEnum;
import gov.va.med.cds.exception.FilterCacheException;
import gov.va.med.cds.tfs.util.FilterMetaDataHelper;
import gov.va.med.cds.util.StreamUtil;

import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;


/**
 * 
 * This class is used by LoadFilterSchemasIntoDBTest in order to load filter meta data from the
 * file system located in (redrock-core/filtercache).
 *
 */
public class FilterFileSystemCacheManager
{
    public static final String FILTER_RESOURCE_PATH_PREFIX = "file:";
    private Map<String, Properties> filterSchemaMetaDataMap = new HashMap<String, Properties>();
    private String filterMetadataPath;


    /**
     * This method returns a collection of available filterIds.
     * 
     * @return filterIds
     */
    public Collection<String> getFilterIds( )
    {
        Collection<String> filterIds = new ArrayList<String>();
        for ( Map.Entry<String, Properties> entry : filterSchemaMetaDataMap.entrySet() )
        {
            String filterId = entry.getKey();
            filterIds.add( filterId );
        }
        return filterIds;
    }


    /**
     * This method loads the filterSchema as a String from the metadata file. 
     * 
     * @param String filterId - is the identifier for the the Filter Schema.
     * @return String
     */
    private String getFilterSchemaAsString( String filterId )
    {
        Properties properties = filterSchemaMetaDataMap.get( filterId );

        if ( null != properties )
        {
            String filePath = properties.getProperty( "file" );
            File file = null;
            if ( ( null != filePath ) && ( 0 < filePath.length() ) )
            {
                try
                {
                    filePath = filePath.replace( '\\', File.separatorChar );
                    file = new File( filePath );
                    String filerSchemaPath = FILTER_RESOURCE_PATH_PREFIX + file.getAbsolutePath();
                    PathMatchingResourcePatternResolver pathResolver = new PathMatchingResourcePatternResolver();
                    Resource[] schemaResources = pathResolver.getResources( filerSchemaPath );
                    return StreamUtil.resourceToString( schemaResources[0] );
                }
                catch ( IOException e )
                {
                    throw new FilterCacheException( ErrorCodeEnum.CANNOT_FIND_FILTER_SCHEMA, e, "Couldn't load the filter from path: "
                                    + file.getAbsolutePath(), e.getMessage() );
                }
            }
        }
        return null;
    }


    /**
     * This method returns all of the metadata associated with a given filterId.
     * Metadata in the file:
            name=Lab_Single_Patient_All_Data_Filter
            id=LAB_SINGLE_PATIENT_ALL_DATA_FILTER
            file=filtercache/vhim_4_00/Lab_Single_Patient_All_Data_Filter.xsd
            requestType=Read
            testOnly=false
            targetNamespace=Clinicaldata
            vhimVersion=Vhim_4_00
            description=Filter
            entryPoint=[LabTestPromise]
     *
     * returns FilterMetaData
     */
    public FilterMetaDataInterface getFilterMetadata( String filterId )
    {
        FilterMetaDataInterface filterMetaData = null;
        Properties filterMetaProps = filterSchemaMetaDataMap.get( filterId );
        if ( null != filterMetaProps )
        {
            filterMetaData = new FilterMetaData();
            filterMetaData.setFilterId( filterMetaProps.getProperty( "id" ) );
            HashSet<String> vhimVersions = new HashSet<String>();
            vhimVersions.add( filterMetaProps.getProperty( "vhimVersion" ) );
            filterMetaData.setVhimVersions( vhimVersions );
            filterMetaData.setFilterDescription( filterMetaProps.getProperty( "description" ) );
            filterMetaData.setStatus( "ACTIVE" );
            filterMetaData.setFilterSchemaXml( this.getFilterSchemaAsString( filterId ) );
            filterMetaData.setFilterSchema( this.getFilterSchemaAsString( filterId ) );
            filterMetaData.setEntryFilters( FilterMetaDataHelper.buildEntryFilters( filterMetaProps.getProperty( "entryPoint" ) ) );
        }
        return filterMetaData;
    }


    /**
     * This method loads the metadata property file into a map for the test.
     * 
     * @param File filterSchemaPropFile - is the file handle to the property file.
     * @throws IOException
     */
    private void loadFilterSchemaMetaDataIntoMap( File filterSchemaPropFile )
        throws IOException
    {
        FileInputStream propInputStream = new FileInputStream( filterSchemaPropFile );
        Properties filterSchemaProps = new Properties();
        filterSchemaProps.load( propInputStream );
        propInputStream.close();

        boolean testOnly = Boolean.parseBoolean( filterSchemaProps.getProperty( "testOnly", "false" ) );

        if ( !testOnly )
        {
            filterSchemaMetaDataMap.put( filterSchemaProps.getProperty( "id" ), filterSchemaProps );
        }
    }


    public void setFilterMetadataPath( String filterMetadataPath )
        throws IOException
    {
        this.filterMetadataPath = filterMetadataPath;
        loadFilterSchemaMetaDataIntoMap();

    }


    /**
     * This method loads a Filter Schema from the properties file into the local map.
     * 
     * @throws IOException
     */
    private void loadFilterSchemaMetaDataIntoMap( )
        throws IOException
    {
        //String filterMetadataPath = properties.getProperty( "path", "." );
        File dir = new File( filterMetadataPath );
        if ( !dir.exists() )
        {
            return;
        }

        if ( dir.isFile() )
        {
            loadFilterSchemaMetaDataIntoMap( dir );
        }
        else
        {
            File[] files = dir.listFiles( new FileFilter()
            {
                public boolean accept( File pathname )
                {
                    return ( pathname.isFile() && pathname.getName().endsWith( ".meta" ) );
                }
            } );

            for ( int i = 0; i < files.length; i++ )
            {
                loadFilterSchemaMetaDataIntoMap( files[i] );
            }
        }
    }

}
