/*
 * Copyright 2000-2010 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.openapi.vcs;

import com.intellij.util.PairProcessor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;

/**
 * @author irengrig
 */
public class AreaMap<Key, Val> {
  protected final List<Key> myKeys;
  protected final Map<Key, Val> myMap;
  // [admittedly] parent, [-"-] child
  protected final PairProcessor<Key, Key> myKeysResemblance;
  private final Comparator<Key> myComparator;

  public static<Key extends Comparable<Key>, Val> AreaMap<Key, Val> create(final PairProcessor<Key, Key> keysResemblance) {
    return new AreaMap<Key,Val>(keysResemblance, new ComparableComparator<Key>());
  }

  public static<Key, Val> AreaMap<Key, Val> create(final PairProcessor<Key, Key> keysResemblance, final Comparator<Key> comparator) {
    return new AreaMap<Key,Val>(keysResemblance, comparator);
  }

  protected AreaMap(final PairProcessor<Key, Key> keysResemblance, final Comparator<Key> comparator) {
    myKeysResemblance = keysResemblance;
    myComparator = comparator;
    myKeys = new LinkedList<Key>();
    myMap = new HashMap<Key, Val>();
  }

  public void putAll(final AreaMap<Key, Val> other) {
    myKeys.addAll(other.myKeys);
    myMap.putAll(other.myMap);
  }

  public void put(final Key key, final Val val) {
    putImpl(key, val);
  }

  protected int putIfNoParent(final Key key, final Val val) {
    if(myMap.put(key, val) != null) {
      return -1;
    }

    if (myKeys.isEmpty()) {
      myKeys.add(key);
      return 0;
    }

    final int idx = Collections.binarySearch(myKeys, key, myComparator);
    if (idx < 0) {
      // insertion, no copy exist
      final int insertionIdx = - idx - 1;
      // check parent
      for (final ListIterator<Key> listIterator = myKeys.listIterator(insertionIdx); listIterator.hasPrevious();) {
        final Key previous = listIterator.previous();
        if (myKeysResemblance.process(previous, key)) {
          myMap.remove(key);
          return -1;
        }
      }
      // insertionIdx not necessarily exist
      myKeys.add(insertionIdx, key);
      return insertionIdx;
    }
    assert true;
    myMap.remove(key);
    return -1;
  }

  protected int putImpl(final Key key, final Val val) {
    myMap.put(key, val);

    if (myKeys.isEmpty()) {
      myKeys.add(key);
      return 0;
    }

    final int idx = Collections.binarySearch(myKeys, key, myComparator);
    if (idx < 0) {
      // insertion, no copy exist
      final int insertionIdx = - idx - 1;
      // insertionIdx not necessarily exist
      myKeys.add(insertionIdx, key);
      return insertionIdx;
    }
    return idx;
  }

  public Collection<Val> values() {
    return Collections.unmodifiableCollection(myMap.values());
  }

  public Collection<Key> keySet() {
    return Collections.unmodifiableCollection(myKeys);
  }

  @Nullable
  public Val getExact(final Key key) {
    return myMap.get(key);
  }

  public void removeByValue(@NotNull final Val val) {
    for (Iterator<Key> iterator = myKeys.iterator(); iterator.hasNext();) {
      final Key key = iterator.next();
      final Val current = myMap.get(key);
      if (val.equals(current)) {
        iterator.remove();
        myMap.remove(key);
        return;
      }
    }
  }

  public void remove(final Key key) {
    myKeys.remove(key);
    myMap.remove(key);
  }

  public boolean contains(final Key key) {
    return myKeys.contains(key);
  }

  public void getSimiliar(final Key key, final PairProcessor<Key, Val> consumer) {
    final int idx = Collections.binarySearch(myKeys, key, myComparator);
    if (idx < 0) {
      final int insertionIdx = - idx - 1;
      // take item before
      final int itemBeforeIdx = insertionIdx - 1;
      if (itemBeforeIdx >= 0) {
        for (ListIterator<Key> iterator = myKeys.listIterator(itemBeforeIdx + 1); iterator.hasPrevious(); ) {
          final Key candidate = iterator.previous();
          if (! myKeysResemblance.process(candidate, key)) continue;
          if (consumer.process(candidate, myMap.get(candidate))) break;     // if need only a part of keys
        }
      }
    } else {
      consumer.process(key, myMap.get(key));
    }
  }
  
  public boolean isEmpty() {
    return myKeys.isEmpty();
  }

  public void clear() {
    myKeys.clear();
    myMap.clear();
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    AreaMap areaMap = (AreaMap)o;

    if (!myKeys.equals(areaMap.myKeys)) return false;
    if (!myMap.equals(areaMap.myMap)) return false;

    return true;
  }

  @Override
  public int hashCode() {
    int result = myKeys.hashCode();
    result = 31 * result + myMap.hashCode();
    return result;
  }
}
