/**
 * Copyright (C) 2014-2016 Philip Helger (www.helger.com)
 * philip[at]helger[dot]com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.helger.commons.collection.ext;

import java.util.Collections;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import com.helger.commons.annotation.ReturnsMutableCopy;
import com.helger.commons.lang.ICloneable;
import com.helger.commons.state.EChange;

public interface ICommonsSet <ELEMENTTYPE> extends
                             Set <ELEMENTTYPE>,
                             ICommonsCollection <ELEMENTTYPE>,
                             ICloneable <ICommonsSet <ELEMENTTYPE>>
{
  /**
   * Create a new empty set. Overwrite this if you don't want to use
   * {@link CommonsHashSet}.
   *
   * @return A new empty set. Never <code>null</code>.
   * @param <T>
   *        Set element type
   */
  @Nonnull
  @ReturnsMutableCopy
  default <T> ICommonsSet <T> createInstance ()
  {
    return new CommonsHashSet <> ();
  }

  @Nonnull
  @ReturnsMutableCopy
  default ICommonsSet <ELEMENTTYPE> getAll (@Nullable final Predicate <? super ELEMENTTYPE> aFilter)
  {
    if (aFilter == null)
      return getClone ();

    final ICommonsSet <ELEMENTTYPE> ret = createInstance ();
    findAll (aFilter, ret::add);
    return ret;
  }

  @Nonnull
  @ReturnsMutableCopy
  default <DSTTYPE> ICommonsSet <DSTTYPE> getAllMapped (@Nonnull final Function <? super ELEMENTTYPE, DSTTYPE> aMapper)
  {
    final ICommonsSet <DSTTYPE> ret = createInstance ();
    findAllMapped (aMapper, ret::add);
    return ret;
  }

  @Nonnull
  @ReturnsMutableCopy
  default <DSTTYPE> ICommonsSet <DSTTYPE> getAllMapped (@Nullable final Predicate <? super ELEMENTTYPE> aFilter,
                                                        @Nonnull final Function <? super ELEMENTTYPE, DSTTYPE> aMapper)
  {
    final ICommonsSet <DSTTYPE> ret = createInstance ();
    findAllMapped (aFilter, aMapper, ret::add);
    return ret;
  }

  @Nonnull
  @ReturnsMutableCopy
  default <DSTTYPE extends ELEMENTTYPE> ICommonsSet <DSTTYPE> getAllInstanceOf (@Nonnull final Class <DSTTYPE> aDstClass)
  {
    final ICommonsSet <DSTTYPE> ret = createInstance ();
    findAllInstanceOf (aDstClass, ret::add);
    return ret;
  }

  /**
   * Replace an existing item in this Set.
   * 
   * @param aElement
   *        The new element to be added.
   * @return {@link EChange#CHANGED} if a previous item was removed,
   *         <code>false</code> if this element was simply added.
   */
  @Nonnull
  default EChange replace (@Nullable final ELEMENTTYPE aElement)
  {
    final EChange eChange = EChange.valueOf (remove (aElement));
    add (aElement);
    return eChange;
  }

  @Nonnull
  default Set <ELEMENTTYPE> getAsUnmodifiable ()
  {
    return Collections.unmodifiableSet (this);
  }
}

@@ -1018,50 +1018,8 @@
 le;%0D
-%0Aimport com.helger.commons.state.EChange;%0D
 %0A%0D%0Ap
@@ -2963,17 +2963,16 @@
 t.%0D%0A   *
- 
 %0D%0A   * @
@@ -3046,31 +3046,25 @@
 urn 
-%7B@link EChange#CHANGED%7D
+%3Ccode%3Etrue%3C/code%3E
  if 
@@ -3189,23 +3189,23 @@
 default 
-EChange
+boolean
  replace
@@ -3264,43 +3264,27 @@
 nal 
-EChange eChange = EChange.valueOf (
+boolean bRemoved = 
 remo
@@ -3296,17 +3296,16 @@
 Element)
-)
 ;%0D%0A    a
@@ -3335,15 +3335,16 @@
 urn 
-eChange
+bRemoved
 ;%0D%0A 

Changed return type to boolean