/*
 * Copyright (c) 2004-2014 Eike Stepper (Berlin, Germany) 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:
 *    Eike Stepper - initial API and implementation
 */
package org.eclipse.emf.cdo.explorer.ui.checkouts;

import org.eclipse.emf.cdo.CDOElement;
import org.eclipse.emf.cdo.explorer.ui.bundle.OM;
import org.eclipse.emf.cdo.util.ObjectNotFoundException;

import org.eclipse.net4j.util.container.IContainerDelta;
import org.eclipse.net4j.util.container.IContainerEvent;
import org.eclipse.net4j.util.container.IPluginContainer;
import org.eclipse.net4j.util.event.IEvent;
import org.eclipse.net4j.util.event.IListener;
import org.eclipse.net4j.util.factory.IFactory;
import org.eclipse.net4j.util.factory.IFactoryKey;
import org.eclipse.net4j.util.factory.ProductCreationException;
import org.eclipse.net4j.util.lifecycle.ILifecycleEvent;
import org.eclipse.net4j.util.registry.IRegistry;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Eike Stepper
 */
public interface CDOCheckoutContentModifier
{
  public Object[] modifyChildren(Object parent, Object[] children);

  /**
   * @author Eike Stepper
   */
  public static abstract class Factory extends org.eclipse.net4j.util.factory.Factory
  {
    public static final String PRODUCT_GROUP = "org.eclipse.emf.cdo.explorer.ui.checkouts.contentModifiers";

    public Factory(String type)
    {
      super(PRODUCT_GROUP, type);
    }

    public abstract CDOCheckoutContentModifier create(String description) throws ProductCreationException;
  }

  /**
   * @author Eike Stepper
   */
  public static final class Registry implements CDOCheckoutContentModifier, IListener
  {
    public static final Registry INSTANCE = new Registry();

    private final Map<String, CDOCheckoutContentModifier> modifiers = new LinkedHashMap<String, CDOCheckoutContentModifier>();

    private Registry()
    {
      IRegistry<IFactoryKey, IFactory> factories = IPluginContainer.INSTANCE.getFactoryRegistry();
      for (Map.Entry<IFactoryKey, IFactory> entry : factories.getElements())
      {
        updateModifiers(entry, IContainerDelta.Kind.ADDED);
      }

      factories.addListener(this);
    }

    private List<CDOCheckoutContentModifier> getModifiers()
    {
      synchronized (modifiers)
      {
        if (modifiers.isEmpty())
        {
          return null;
        }

        return new ArrayList<CDOCheckoutContentModifier>(modifiers.values());
      }
    }

    public Object[] modifyChildren(Object parent, Object[] children)
    {
      List<CDOCheckoutContentModifier> modifiers = getModifiers();
      if (modifiers != null)
      {
        for (int i = 0; i < children.length; i++)
        {
          Object child = children[i];
          CDOElement.removeFrom(child);
        }

        for (CDOCheckoutContentModifier modifier : modifiers)
        {
          try
          {
            children = modifier.modifyChildren(parent, children);
          }
          catch (ObjectNotFoundException ex)
          {
            // Do nothing
          }
          catch (Exception ex)
          {
            OM.LOG.error(ex);
          }
        }
      }

      return children;
    }

    public void notifyEvent(IEvent event)
    {
      if (event instanceof IContainerEvent)
      {
        @SuppressWarnings("unchecked")
        IContainerEvent<Map.Entry<IFactoryKey, IFactory>> e = (IContainerEvent<Map.Entry<IFactoryKey, IFactory>>)event;

        for (IContainerDelta<Map.Entry<IFactoryKey, IFactory>> delta : e.getDeltas())
        {
          Map.Entry<IFactoryKey, IFactory> entry = delta.getElement();
          updateModifiers(entry, delta.getKind());
        }
      }
      else if (event instanceof ILifecycleEvent)
      {
        ILifecycleEvent e = (ILifecycleEvent)event;
        if (e.getKind() == ILifecycleEvent.Kind.DEACTIVATED)
        {
          IPluginContainer.INSTANCE.getFactoryRegistry().removeListener(this);

          synchronized (modifiers)
          {
            modifiers.clear();
          }
        }
      }
    }

    private void updateModifiers(Map.Entry<IFactoryKey, IFactory> entry, IContainerDelta.Kind deltaKind)
    {
      try
      {
        IFactoryKey key = entry.getKey();
        if (Factory.PRODUCT_GROUP.equals(key.getProductGroup()))
        {
          String type = key.getType();
          if (deltaKind == IContainerDelta.Kind.ADDED)
          {
            CDOCheckoutContentModifier modifier = (CDOCheckoutContentModifier)IPluginContainer.INSTANCE
                .getElement(Factory.PRODUCT_GROUP, type, null);

            synchronized (modifiers)
            {
              modifiers.put(type, modifier);
            }
          }
          else
          {
            synchronized (modifiers)
            {
              modifiers.remove(type);
            }
          }
        }
      }
      catch (Exception ex)
      {
        OM.LOG.error(ex);
      }
    }
  }
}
