package org.apache.samoa.topology.impl;

/*
 * #%L
 * SAMOA
 * %%
 * Copyright (C) 2013 Yahoo! Inc.
 * %%
 * 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.
 * #L%
 */

import java.util.LinkedList;
import java.util.List;

import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.samoa.core.ContentEvent;
import org.apache.samoa.topology.AbstractStream;
import org.apache.samoa.topology.IProcessingItem;
import org.apache.samoa.utils.StreamDestination;

/**
 * Stream for multithreaded engine.
 * 
 * @author Anh Thu Vu
 * 
 */
public class ThreadsStream extends AbstractStream {

  private List<StreamDestination> destinations;
  private int counter = 0;
  private int maxCounter = 1;

  public ThreadsStream(IProcessingItem sourcePi) {
    destinations = new LinkedList<StreamDestination>();
  }

  public void addDestination(StreamDestination destination) {
    destinations.add(destination);
    maxCounter *= destination.getParallelism();
  }

  public List<StreamDestination> getDestinations() {
    return this.destinations;
  }

  private int getNextCounter() {
    if (maxCounter > 0 && counter >= maxCounter)
      counter = 0;
    this.counter++;
    return this.counter;
  }

  @Override
  public synchronized void put(ContentEvent event) {
    this.put(event, this.getNextCounter());
  }

  private void put(ContentEvent event, int counter) {
    ThreadsProcessingItem pi;
    int parallelism;
    for (StreamDestination destination : destinations) {
      pi = (ThreadsProcessingItem) destination.getProcessingItem();
      parallelism = destination.getParallelism();
      switch (destination.getPartitioningScheme()) {
      case SHUFFLE:
        pi.processEvent(event, counter % parallelism);
        break;
      case GROUP_BY_KEY:
        pi.processEvent(event, getPIIndexForKey(event.getKey(), parallelism));
        break;
      case BROADCAST:
        for (int p = 0; p < parallelism; p++) {
          pi.processEvent(event, p);
        }
        break;
      }
    }
  }

  private static int getPIIndexForKey(String key, int parallelism) {
    // If key is null, return a default index: 0
    if (key == null)
      return 0;

    // HashCodeBuilder object does not have reset() method
    // So all objects that get appended will be included in the
    // computation of the hashcode.
    // To avoid initialize a HashCodeBuilder for each event,
    // here I use the static method with reflection on the event's key
    int index = HashCodeBuilder.reflectionHashCode(key, true) % parallelism;
    if (index < 0) {
      index += parallelism;
    }
    return index;
  }

}
