/**
 * 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.hadoop.mapreduce;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.Writable;

public class Counters implements Writable,Iterable<CounterGroup> {
  /**
   * A cache from enum values to the associated counter. Dramatically speeds up
   * typical usage.
   */
  private Map<Enum<?>, Counter> cache = new IdentityHashMap<Enum<?>, Counter>();

  private TreeMap<String, CounterGroup> groups = 
      new TreeMap<String, CounterGroup>();
  
  public Counters() {
  }
  
  /**
   * Utility method to  create a Counters object from the 
   * org.apache.hadoop.mapred counters
   * @param counters
   */
  public Counters(org.apache.hadoop.mapred.Counters counters) {
    for(org.apache.hadoop.mapred.Counters.Group group: counters) {
      String name = group.getName();
      CounterGroup newGroup = new CounterGroup(name, group.getDisplayName());
      groups.put(name, newGroup);
      for(Counter counter: group) {
        newGroup.addCounter(counter);
      }
    }
  }

  /** Add a group. */
  public void addGroup(CounterGroup group) {
    groups.put(group.getName(), group);
  }

  public Counter findCounter(String groupName, String counterName) {
    CounterGroup grp = getGroup(groupName);
    return grp.findCounter(counterName);
  }

  /**
   * Find the counter for the given enum. The same enum will always return the
   * same counter.
   * @param key the counter key
   * @return the matching counter object
   */
  public synchronized Counter findCounter(Enum<?> key) {
    Counter counter = cache.get(key);
    if (counter == null) {
      counter = findCounter(key.getDeclaringClass().getName(), key.toString());
      cache.put(key, counter);
    }
    return counter;    
  }

  /**
   * Returns the names of all counter classes.
   * @return Set of counter names.
   */
  public synchronized Collection<String> getGroupNames() {
    return groups.keySet();
  }

  @Override
  public Iterator<CounterGroup> iterator() {
    return groups.values().iterator();
  }

  /**
   * Returns the named counter group, or an empty group if there is none
   * with the specified name.
   */
  public synchronized CounterGroup getGroup(String groupName) {
    CounterGroup grp = groups.get(groupName);
    if (grp == null) {
      grp = new CounterGroup(groupName);
      groups.put(groupName, grp);
    }
    return grp;
  }

  /**
   * Returns the total number of counters, by summing the number of counters
   * in each group.
   */
  public synchronized  int countCounters() {
    int result = 0;
    for (CounterGroup group : this) {
      result += group.size();
    }
    return result;
  }

  /**
   * Write the set of groups.
   * The external format is:
   *     #groups (groupName group)*
   *
   * i.e. the number of groups followed by 0 or more groups, where each 
   * group is of the form:
   *
   *     groupDisplayName #counters (false | true counter)*
   *
   * where each counter is of the form:
   *
   *     name (false | true displayName) value
   */
  @Override
  public synchronized void write(DataOutput out) throws IOException {
    out.writeInt(groups.size());
    for (org.apache.hadoop.mapreduce.CounterGroup group: groups.values()) {
      Text.writeString(out, group.getName());
      group.write(out);
    }
  }
  
  /**
   * Read a set of groups.
   */
  @Override
  public synchronized void readFields(DataInput in) throws IOException {
    int numClasses = in.readInt();
    groups.clear();
    while (numClasses-- > 0) {
      String groupName = Text.readString(in);
      CounterGroup group = new CounterGroup(groupName);
      group.readFields(in);
      groups.put(groupName, group);
    }
  }

  /**
   * Return textual representation of the counter values.
   */
  public synchronized String toString() {
    StringBuilder sb = new StringBuilder("Counters: " + countCounters());
    for (CounterGroup group: this) {
      sb.append("\n\t" + group.getDisplayName());
      for (Counter counter: group) {
        sb.append("\n\t\t" + counter.getDisplayName() + "=" + 
                  counter.getValue());
      }
    }
    return sb.toString();
  }

  /**
   * Increments multiple counters by their amounts in another Counters 
   * instance.
   * @param other the other Counters instance
   */
  public synchronized void incrAllCounters(Counters other) {
    for(Map.Entry<String, CounterGroup> rightEntry: other.groups.entrySet()) {
      CounterGroup left = groups.get(rightEntry.getKey());
      CounterGroup right = rightEntry.getValue();
      if (left == null) {
        left = new CounterGroup(right.getName(), right.getDisplayName());
        groups.put(rightEntry.getKey(), left);
      }
      left.incrAllCounters(right);
    }
  }

  public boolean equals(Object genericRight) {
    if (genericRight instanceof Counters) {
      Iterator<CounterGroup> right = ((Counters) genericRight).groups.
                                       values().iterator();
      Iterator<CounterGroup> left = groups.values().iterator();
      while (left.hasNext()) {
        if (!right.hasNext() || !left.next().equals(right.next())) {
          return false;
        }
      }
      return !right.hasNext();
    }
    return false;
  }
  
  public int hashCode() {
    return groups.hashCode();
  }
}
