/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.giraph.edge;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.NullWritable;

import com.google.common.collect.UnmodifiableIterator;

import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntIterator;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;

/**
 * Implementation of {@link OutEdges} with int ids and null edge
 * values, backed by dynamic primitive array.
 * Parallel edges are allowed.
 * Note: this implementation is optimized for space usage,
 * but edge removals are expensive.
 */
public class IntNullArrayEdges
    implements ReuseObjectsOutEdges<IntWritable, NullWritable> {
  /** Array of target vertex ids */
  private IntArrayList neighbors;

  @Override
  public void initialize(Iterable<Edge<IntWritable, NullWritable>> edges) {
    // If the iterable is actually a collection, we can cheaply get the
    // size and initialize the array with the expected capacity.
    if (edges instanceof Collection) {
      int numEdges =
          ((Collection<Edge<IntWritable, NullWritable>>) edges).size();
      initialize(numEdges);
    } else {
      initialize();
    }
    for (Edge<IntWritable, NullWritable> edge : edges) {
      add(edge);
    }
  }

  @Override
  public void initialize(int capacity) {
    neighbors = new IntArrayList(capacity);
  }

  @Override
  public void initialize() {
    neighbors = new IntArrayList();
  }

  @Override
  public int size() {
    return neighbors.size();
  }

  @Override
  public void add(Edge<IntWritable, NullWritable> edge) {
    neighbors.add(edge.getTargetVertexId().get());
  }

  /**
   * Remove edge at position i.
   *
   * @param i Position of edge to be removed
   */
  private void removeAt(int i) {
    // The order of the edges is irrelevant, so we can simply replace
    // the deleted edge with the rightmost element, thus achieving constant
    // time.
    if (i == neighbors.size() - 1) {
      neighbors.popInt();
    } else {
      neighbors.set(i, neighbors.popInt());
    }
  }

  @Override
  public void remove(IntWritable targetVertexId) {
    // Thanks to the constant-time implementation of removeAt(int),
    // we can remove all matching edges in linear time.
    for (int i = neighbors.size() - 1; i >= 0; --i) {
      if (neighbors.get(i) == targetVertexId.get()) {
        removeAt(i);
      }
    }
  }

  @Override
  public Iterator<Edge<IntWritable, NullWritable>> iterator() {
    // Returns an iterator that reuses objects.
    return new UnmodifiableIterator<Edge<IntWritable, NullWritable>>() {
      /** Wrapped neighbors iterator. */
      private IntIterator neighborsIt = neighbors.iterator();
      /** Representative edge object. */
      private Edge<IntWritable, NullWritable> representativeEdge =
          EdgeFactory.create(new IntWritable(), NullWritable.get());

      @Override
      public boolean hasNext() {
        return neighborsIt.hasNext();
      }

      @Override
      public Edge<IntWritable, NullWritable> next() {
        representativeEdge.getTargetVertexId().set(neighborsIt.nextInt());
        return representativeEdge;
      }
    };
  }

  @Override
  public void write(DataOutput out) throws IOException {
    out.writeInt(neighbors.size());
    IntIterator iterator = neighbors.iterator();
    while (iterator.hasNext()) {
      out.writeInt(iterator.nextInt());
    }
  }

  @Override
  public void readFields(DataInput in) throws IOException {
    int numEdges = in.readInt();
    initialize(numEdges);
    for (int i = 0; i < numEdges; ++i) {
      neighbors.add(in.readInt());
    }
  }
}
