/*******************************************************************************
 * Copyright (c) 2007, 2008 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * IBM Corporation - initial API and implementation
 * yyyymmdd bug      Email and other contact information
 * -------- -------- -----------------------------------------------------------
 * 20071024   196997 pmoogk@ca.ibm.com - Peter Moogk
 * 20071113   209701 pmoogk@ca.ibm.com - Peter Moogk
 * 20080111   214907 pmoogk@ca.ibm.com - Peter Moogk
 * 20080214   218996 pmoogk@ca.ibm.com - Peter Moogk, Concurrent exception fix
 * 20080325   222095 pmoogk@ca.ibm.com - Peter Moogk
 *******************************************************************************/
package org.eclipse.wst.ws.service.internal.policy;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.expressions.EvaluationContext;
import org.eclipse.core.expressions.EvaluationResult;
import org.eclipse.core.expressions.Expression;
import org.eclipse.core.expressions.IEvaluationContext;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.wst.ws.service.policy.IFilter;
import org.eclipse.wst.ws.service.policy.IServicePolicy;
import org.eclipse.wst.ws.service.policy.IStateEnumerationItem;
import org.eclipse.wst.ws.service.policy.ServicePolicyActivator;
import org.eclipse.wst.ws.service.policy.listeners.IPolicyChildChangeListener;
import org.eclipse.wst.ws.service.policy.listeners.IPolicyPlatformLoadListener;
import org.eclipse.wst.ws.service.policy.listeners.IPolicyPlatformProjectLoadListener;
import org.osgi.service.prefs.BackingStoreException;


public class ServicePolicyPlatformImpl 
{
  private List<IPolicyPlatformLoadListener>        loadListeners;
  private Map<String, ServicePolicyImpl>           committedPolicyMap;
  private Map<String, ServicePolicyImpl>           policyMap;
  private Map<String, List<IStateEnumerationItem>> enumList;
  private Map<String, StateEnumerationItemImpl>    enumItemList;
  private Map<IProject, ProjectEntry>              enabledProjectMap;
  private List<Expression>                         enabledList;
  private List<IPolicyChildChangeListener>         childChangeListeners;
  private List<IPolicyChildChangeListener>         childChangeListenersOnCommit;
  private List<IServicePolicy>                     commitChildChangePolicy;
  private List<Boolean>                            commitChildChangeAdded;
  private List<IServicePolicy>                     queuedChildChangePolicy;
  private List<Boolean>                            queuedChildChangeAdded;
  private List<IPolicyPlatformProjectLoadListener> projectPlatformListeners;
  
  public ServicePolicyPlatformImpl()
  {
  }
  
  public void load()
  {
    ServicePolicyRegistry registry  = new ServicePolicyRegistry( this );
    List<String>          localIds  = LocalUtils.getLocalPolicyIds();
    
    loadListeners     = new Vector<IPolicyPlatformLoadListener>();
    policyMap         = new HashMap<String, ServicePolicyImpl>();
    enumList          = new HashMap<String, List<IStateEnumerationItem>>();
    enumItemList      = new HashMap<String, StateEnumerationItemImpl>();
    enabledProjectMap = new HashMap<IProject, ProjectEntry>();
    enabledList       = new Vector<Expression>();
    
    childChangeListeners         = new Vector<IPolicyChildChangeListener>();
    childChangeListenersOnCommit = new Vector<IPolicyChildChangeListener>();
    commitChildChangePolicy      = new Vector<IServicePolicy>();
    commitChildChangeAdded       = new Vector<Boolean>();
    projectPlatformListeners     = new Vector<IPolicyPlatformProjectLoadListener>();
    
    registry.load( loadListeners, policyMap, enumList, enumItemList );
    
    // This first loop through the ids will only create service policy objects
    // without populating them with there values.
    for( String localPolicyId : localIds )
    {
      ServicePolicyImpl localPolicy = new ServicePolicyImpl( false, localPolicyId, this );
      
      policyMap.put( localPolicyId, localPolicy );
    }
    
    // This second loop will populate the service policy values and
    // crossreference parent and child service policies.
    for( String localPolicyId : localIds )
    {
      LocalUtils.loadLocalPolicy( localPolicyId, this );
    }
       
    for( IPolicyPlatformLoadListener loadListener : loadListeners )
    {
      loadListener.load();
    }
    
    commitChanges( false );   

    // Commit any project level changes that have been made by load listeners.
    for( IProject project : enabledProjectMap.keySet() )
    {
      commitChanges( project );
    }
  }
  
  public void addEnabledExpression( Expression expression )
  {
    if( expression != null )
    {
      enabledList.add( expression );
    }
  }
  
  public boolean isEnabled( Object object )
  {
    boolean            result = false;
    IEvaluationContext context = new EvaluationContext( null, object );
    context.addVariable( "selection", object ); //$NON-NLS-1$
    context.setAllowPluginActivation( true );
    
    for( Expression enabledItem : enabledList )
    {
      try
      {
        EvaluationResult expResult = enabledItem.evaluate( context );
        
        // If any expression returns TRUE or NOT_LOADED we will return true as
        // the result.
        if( expResult != EvaluationResult.FALSE )
        {
          result = true;
          break;
        }
      }
      catch( CoreException exc )
      {
        // Ignore the expression if an exception occurs.
        ServicePolicyActivator.logError( "Error evaluating enablement expression.", exc ); //$NON-NLS-1$
      }
    }
    
    return result;
  }
  
  public void commitChanges( boolean saveLocals )
  {
    List<String> localIds = new Vector<String>();
    
    if( saveLocals ) LocalUtils.removeAllPreferencePolicies( null, null );
    
    // Fire child change events for commit listeners
    for( IPolicyChildChangeListener listener : childChangeListenersOnCommit )
    {
      listener.childChange( commitChildChangePolicy, commitChildChangeAdded );
    }
    
    removeDeletedPreferenceData();
    
    commitChildChangePolicy = new Vector<IServicePolicy>();
    commitChildChangeAdded  = new Vector<Boolean>();
    
    for( ServicePolicyImpl policy : policyMap.values() )
    {
      policy.commitChanges();
      
      if( saveLocals && !policy.isPredefined() )
      {
        LocalUtils.saveLocalPolicy( policy );
        localIds.add( policy.getId() );
      }
    }
    
    if( saveLocals ) LocalUtils.saveLocalIds( localIds );
    
    committedPolicyMap = new HashMap<String, ServicePolicyImpl>();
    committedPolicyMap.putAll( policyMap );
    ServicePolicyActivator.getDefault().savePluginPreferences();
  }
  
  private void removeDeletedPreferenceData()
  {
    for( int index = 0; index < commitChildChangePolicy.size(); index++ )
    {
      IServicePolicy policy = commitChildChangePolicy.get( index );
      boolean        added  = commitChildChangeAdded.get( index );
      
      if( !added )
      {
        // Add policy is being deleted.  We need to remove any state data
        // for this policy at the workspace level and the project level.
        LocalUtils.removeAllPreferencePolicies( policy.getId(), null );
        
        for( IProject proj : enabledProjectMap.keySet() )
        {
          if( proj.exists() && proj.isOpen() )
          {
            IEclipsePreferences projPrefs = new ProjectScope( proj ).getNode( ServicePolicyActivator.PLUGIN_ID );
            LocalUtils.removeAllPreferencePolicies( policy.getId(), projPrefs );
          
            try
            {
              projPrefs.flush();
            }
            catch( BackingStoreException exc )
            {
              ServicePolicyActivator.logError( "Error flushing project properties.", exc ); //$NON-NLS-1$         
            }
          }
        }
      }
    }
  }
  
  /**
   * This method is called internally to remove a service policy.
   * 
   * @param policy
   */
  public void removePolicy( IServicePolicy policy )
  {
    policyMap.remove( policy.getId() );
    fireChildChangeEvent( policy, false );
  }
  
  /**
   * This method is only called from the platform API
   * 
   * @param policy
   */
  public void removePlatformPolicy( IServicePolicy policy )
  {
    if( policy.isPredefined() ) return;
    
    IServicePolicy parent = policy.getParentPolicy();
    
    if( parent == null )
    {
      // Remove any children first
      List<IServicePolicy> children = new Vector<IServicePolicy>( policy.getChildren() );
      
      for( IServicePolicy child : children )
      {
        policy.removeChild( child );  
      }
      
      removePolicy( (ServicePolicyImpl)policy);
    }
    else
    {
      parent.removeChild( policy );
    }
  }
  
  public void addChildChangeListener( IPolicyChildChangeListener listener, boolean onCommit )
  {
    if( onCommit )
    {
      childChangeListenersOnCommit.add( listener );
    }
    else
    {
      childChangeListeners.add( listener );
    }
  }
  
  public void removeChildChangeListener( IPolicyChildChangeListener listener, boolean onCommit )
  {
    if( onCommit )
    {
      childChangeListenersOnCommit.remove( listener );
    }
    else
    {
      childChangeListeners.remove( listener );
    }
  }
  
  public void queueChildChangeListeners( boolean queue )
  {
    if( queue && queuedChildChangeAdded == null )
    {
      queuedChildChangeAdded = new Vector<Boolean>();
      queuedChildChangePolicy = new Vector<IServicePolicy>();
    }
    else if( !queue && queuedChildChangeAdded != null )
    {
      // Queuing has been turned off so we will fire all the queued events.
      for( IPolicyChildChangeListener listener : childChangeListeners )
      {
        listener.childChange( queuedChildChangePolicy, queuedChildChangeAdded );
      }
      
      queuedChildChangeAdded = null;
      queuedChildChangePolicy = null;
    }
  }
  
  public void fireChildChangeEvent( IServicePolicy policy, boolean isAdd )
  {
    if( queuedChildChangeAdded == null )
    {
      List<IServicePolicy> policyList = new Vector<IServicePolicy>(1);
      List<Boolean>        addedList  = new Vector<Boolean>(1);
      
      policyList.add( policy );
      addedList.add( isAdd );
      
      for( IPolicyChildChangeListener listener : childChangeListeners )
      {
        listener.childChange( policyList, addedList );     
      }
    }
    else
    {
      queuedChildChangeAdded.add( isAdd );
      queuedChildChangePolicy.add( policy );
    }
    
    commitChildChangeAdded.add( isAdd );
    commitChildChangePolicy.add( policy );
  }
  
  public void commitChanges( IProject project )
  {
    for( ServicePolicyImpl policy : policyMap.values() )
    {
      ((PolicyStateImpl)policy.getPolicyState( project )).commitChanges();
    }
    
    ProjectEntry entry = getProjectEntry( project );
    
    entry.isEnabledCommitted = entry.isEnabled;  
    setProjectEnabled( project, entry.isEnabledCommitted );
        
    try
    {
      IEclipsePreferences projectPrefs = new ProjectScope( project ).getNode( ServicePolicyActivator.PLUGIN_ID );
      
      projectPrefs.flush();
    }
    catch( BackingStoreException exc )
    {
      ServicePolicyActivator.logError( "Error while committing project preferences.", exc ); //$NON-NLS-1$
    }
    
  }
  
  public void discardChanges()
  {
    policyMap = new HashMap<String, ServicePolicyImpl>();
    policyMap.putAll( committedPolicyMap );
    
    commitChildChangePolicy = new Vector<IServicePolicy>();
    commitChildChangeAdded  = new Vector<Boolean>();
    
    for( ServicePolicyImpl policy : committedPolicyMap.values() )
    {
      policy.discardChanges();
    }    
  }
  
  public void discardChanges( IProject project )
  {
    for( ServicePolicyImpl policy : policyMap.values() )
    {
      ((PolicyStateImpl)policy.getPolicyState( project )).discardChanges();
    }
    
    ProjectEntry entry = getProjectEntry( project );
    
    entry.isEnabled = entry.isEnabledCommitted;  
  }
  
  public void restoreDefaults()
  {
    Vector<ServicePolicyImpl> tempPolicyValues 
       = new Vector<ServicePolicyImpl>( policyMap.values() );
    
    for( ServicePolicyImpl policy : tempPolicyValues )
    {
      policy.restoreDefaults();
    }
  }
  
  public void restoreDefaults( IProject project )
  {
    for( ServicePolicyImpl policy : policyMap.values() )
    {
      policy.restoreDefaults( project );
    }    
  }
  
  public Set<String> getAllPolicyIds()
  {
    return policyMap.keySet();
  }
    
  public List<IServicePolicy> getRootServicePolicies( IFilter filter )
  {
    List<IServicePolicy> rootPolicies = new Vector<IServicePolicy>();
    
    for( String policyId : policyMap.keySet() )
    {
      ServicePolicyImpl policy = policyMap.get( policyId );
      
      if( policy.getParentPolicy() == null )
      {
        if( filter == null || (filter != null && filter.accept( policy )) )
        {
          rootPolicies.add( policy );
        }
      }
    }
    
    return rootPolicies;
  }
  
  public ServicePolicyImpl createServicePolicy( IServicePolicy parent, 
                                                String         id, 
                                                String         enumListId, 
                                                String         defaultEnumId )
  {
    if( id == null ) id = "org.eclipse.wst.ws.service.policy.id"; //$NON-NLS-1$
    
    String            uniqueId = makeUniqueId( id );
    ServicePolicyImpl policy   = new ServicePolicyImpl( false, uniqueId, this );
    
    policy.setParent( (ServicePolicyImpl)parent );
    policy.setEnumListId( enumListId );
    policy.setDefaultEnumId( defaultEnumId );
    policyMap.put( uniqueId, policy );
    fireChildChangeEvent( policy, true );
    
    return policy;
  }
  
  public ServicePolicyImpl getServicePolicy( String id )
  {
    return id == null ? null : policyMap.get( id );  
  }
  
  public List<IStateEnumerationItem> getStateEnumeration( String enumId )
  {
    return enumList.get( enumId ); 
  }
  
  public IStateEnumerationItem getStateItemEnumeration( String stateItemId )
  {
    return enumItemList.get( stateItemId );
  }
  
  public boolean isProjectPreferencesEnabled( IProject project )
  {
    ProjectEntry entry  = getProjectEntry( project );
    
    return entry.isEnabled;
  }
  
  private boolean getProjectPreferenceEnabled( IProject project )
  {
    String              pluginId          = ServicePolicyActivator.PLUGIN_ID;
    IEclipsePreferences projectPreference = new ProjectScope( project ).getNode( pluginId );
    String              key               = pluginId + ".projectEnabled"; //$NON-NLS-1$
    
    return projectPreference.getBoolean( key, false );    
  }
  
  public void setProjectPreferencesEnabled( IProject project, boolean value )
  {
    ProjectEntry entry  = getProjectEntry( project );
    
    entry.isEnabled = value;
  }
  
  /**
   * Add a project platform listener.  When a particular project is referenced
   * by in the service policy platform this listener will be called the first
   * time the project is loaded into the system.
   * 
   * @param listener the listener
   */
  public void addProjectLoadListener( IPolicyPlatformProjectLoadListener listener )
  {
    projectPlatformListeners.add( listener );
  }
  
  /**
   * Removes a project platform listener.
   * 
   * @param listener the listener
   */
  public void removeProjectLoadListener( IPolicyPlatformProjectLoadListener listener )
  {
    projectPlatformListeners.remove( listener );
  }
  
  private void setProjectEnabled( IProject project, boolean value )
  {
    String              pluginId          = ServicePolicyActivator.PLUGIN_ID;
    IEclipsePreferences projectPreference = new ProjectScope( project ).getNode( pluginId );
    String              key               = pluginId + ".projectEnabled"; //$NON-NLS-1$

    projectPreference.putBoolean( key, value );    
  }
  
  private ProjectEntry getProjectEntry( IProject project )
  {
    ProjectEntry entry  = enabledProjectMap.get( project );
    
    if( entry == null )
    {
      entry = new ProjectEntry();
      enabledProjectMap.put( project, entry );
      entry.isEnabledCommitted = getProjectPreferenceEnabled( project );
      entry.isEnabled = entry.isEnabledCommitted;
      fireProjectLoadListener( project );
    }

    return entry;
  }
  
  private void fireProjectLoadListener( IProject project )
  {
    for( IPolicyPlatformProjectLoadListener listener : projectPlatformListeners )
    {
      listener.load( project );
    }
  }
  
  private String makeUniqueId( String id )
  {
    String  result  = id;
    int     idCount = 1;
    Pattern pattern = Pattern.compile( "\\d*$" ); // Match any numerical digits at the end //$NON-NLS-1$
                                                  // of the string.
    
    while( policyMap.containsKey( result ) )
    {
      Matcher matcher = pattern.matcher( result );
    
      result = matcher.replaceFirst( "" ) + idCount; //$NON-NLS-1$
      idCount++;
    }
    
    return result;
  }
  
  private class ProjectEntry
  {
     boolean isEnabledCommitted;
     boolean isEnabled;
  }
}
