/*
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * 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.intellij.util.xml;

import com.intellij.util.CommonProcessors;
import com.intellij.util.Processor;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;

/**
 * @author peter
 */
public class ModelMergerUtil {

  @Nullable
  public static <T> T getFirstImplementation(final T t) {
    T cur = t;
    while (cur instanceof MergedObject) {
      final List<T> implementations = ((MergedObject<T>)cur).getImplementations();
      cur = implementations.isEmpty()? null : implementations.get(0);
    }
    return cur;
  }

  @Nullable
  public static <T, V> V getImplementation(final Class<V> clazz, final Collection<T> elements) {
    for (final T element : elements) {
      final V implementation = getImplementation(element, clazz);
      if (implementation != null) {
        return implementation;
      }
    }
    return null;
  }

  @Nullable
  public static <T, V> V getImplementation(final Class<V> clazz, final T... elements) {
    return getImplementation(clazz, Arrays.asList(elements));
  }

  @Nullable
  public static <T, V> V getImplementation(final T element, final Class<V> clazz) {
    if (element == null) return null;
    CommonProcessors.FindFirstProcessor<T> processor = new CommonProcessors.FindFirstProcessor<T>() {
      @Override
      public boolean process(final T t) {
        return !ReflectionUtil.isAssignable(clazz, t.getClass()) || super.process(t);
      }
    };
    new ImplementationProcessor<T>(processor, true).process(element);
    return (V)processor.getFoundValue();
  }

  @NotNull
  public static <T, V> Collection<V> getImplementations(final T element, final Class<V> clazz) {
    if (element == null) return Collections.emptyList();
    CommonProcessors.CollectProcessor<T> processor = new CommonProcessors.CollectProcessor<T>() {
      @Override
      public boolean process(final T t) {
        return !ReflectionUtil.isAssignable(clazz, t.getClass()) || super.process(t);
      }
    };
    new ImplementationProcessor<T>(processor, true).process(element);
    return (Collection<V>)processor.getResults();
  }

  @NotNull
  public static <T> List<T> getImplementations(T element) {
    if (element instanceof MergedObject) {
      final MergedObject<T> mergedObject = (MergedObject<T>)element;
      return mergedObject.getImplementations();
    }
    else if (element != null) {
      return Collections.singletonList(element);
    }
    else {
      return Collections.emptyList();
    }
  }

  @NotNull
  public static <T> List<T> getFilteredImplementations(final T element) {
    if (element == null) return Collections.emptyList();
    final CommonProcessors.CollectProcessor<T> processor = new CommonProcessors.CollectProcessor<T>(new ArrayList<T>());
    new ImplementationProcessor<T>(processor, false).process(element);
    return (List<T>)processor.getResults();
  }

  @NotNull
  public static <T> Processor<T> createFilteringProcessor(final Processor<T> processor) {
    return new ImplementationProcessor<T>(processor, false);
  }

  public static class ImplementationProcessor<T> implements Processor<T> {
    private final Processor<T> myProcessor;
    private final boolean myProcessMerged;

    public ImplementationProcessor(Processor<T> processor, final boolean processMerged) {
      myProcessor = processor;
      myProcessMerged = processMerged;
    }

    @Override
    public boolean process(final T t) {
      final boolean merged = t instanceof MergedObject;
      if ((!merged || myProcessMerged) && !myProcessor.process(t)) {
        return false;
      }
      if (merged && !ContainerUtil.process(((MergedObject<T>)t).getImplementations(), this)) {
        return false;
      }
      return true;
    }
  }
}
