// Copyright 2012 Google Inc. All Rights Reserved.
//
// 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.google.enterprise.adaptor;

import static java.util.AbstractMap.SimpleImmutableEntry;
import static java.util.Map.Entry;

import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

/**
 * Allows storing multiple metadata values to a single key.
 * <p>
 * Null keys are invalid as arguments.  Null values are
 * invalid as arguments.
 * <p>
 * This class is mutable and not thread-safe.
 */
public class Metadata implements Iterable<Entry<String, String>> {
  private Map<String, Set<String>> mappings 
      = new TreeMap<String, Set<String>>();

  /** Create empty instance. */
  public Metadata() {
  }

  /** Duplicate. */
  public Metadata(Iterable<Entry<String, String>> m) {
    for (Entry<String, String> e : m) {
      add(e.getKey(), e.getValue());
    }    
  }

  /** Make v be only value associated with key. */
  public void set(String k, String v) {
    if (null == k) {
      throw new NullPointerException();
    }
    if (null == v) {
      throw new NullPointerException();
    }
    TreeSet<String> single = new TreeSet<String>();
    single.add(v);
    mappings.put(k, single);
  }

  /** Throws NullPointerException if a null is found. */
  private static void assureNoNulls(Set<String> items) {
    // Can't use items.contains(null) because Set is permitted to throw NPE in
    // such a case.
    for (String s : items) {
      if (s == null) {
        throw new NullPointerException();
      }
    }
  }

  /** Make copy of v be the values associated with key. */
  public void set(String k, Set<String> v) {
    if (null == k) {
      throw new NullPointerException();
    }
    if (null == v) {
      throw new NullPointerException();
    }
    assureNoNulls(v);
    if (v.isEmpty()) {
      mappings.remove(k);
    } else {
      v = new TreeSet<String>(v);
      mappings.put(k, v);
    }
  }

  /** Increases values mapped to k with v. */
  public void add(String k, String v) {
    if (null == k) {
      throw new NullPointerException();
    }
    if (null == v) {
      throw new NullPointerException();
    }
    Set<String> found = mappings.get(k);
    if (null == found) {
      set(k, v);
    } else {
      found.add(v);
    }
  }

  /** Replaces entries inside of this metadata with provided ones. */
  public void set(Iterable<Entry<String, String>> it) {
    mappings.clear();
    for (Entry<String, String> e : it) {
      add(e.getKey(), e.getValue());
    }    
  }

  /** Gives unmodifiable reference to inserted values for key, empty if none. */
  public Set<String> getAllValues(String key) {
    Set<String> found = mappings.get(key);
    if (null == found) {
      found = Collections.emptySet(); 
    }
    return Collections.unmodifiableSet(found);
  }

  /** One of the inserted values, or null if none. */
  public String getOneValue(String key) {
    Set<String> found = mappings.get(key);
    String first = null;
    if (null != found) {
      if (found.isEmpty()) {
        throw new AssertionError();
      }
      first = found.iterator().next(); 
    }
    return first;
  }

  /** Get modifiable set of all keys with at least one value. */
  public Set<String> getKeys() {
    return mappings.keySet();
  }

  /**
   * Provides every key and value in immutable entries sorted
   * alphabetically, first by key, and secondly by value.
   * <p>
   * Behaviour is undefined if backing Metadata instance is modified
   * during iteration.
   * <p>
   * remove() is unsupported on returned iterator.
   */
  public Iterator<Entry<String, String>> iterator() {
    return new EntriesIterator();
  }

  /** Loops through keys and for each key all values. */
  private class EntriesIterator implements Iterator<Entry<String, String>> {
    private Iterator<Entry<String, Set<String>>> byKey
        = mappings.entrySet().iterator();
    private String currentKey;
    private Iterator<String> currentValues
        = Collections.<String>emptyList().iterator();

    @Override
    public boolean hasNext() {
      if (currentValues.hasNext()) {
        return true;
      }
      if (!byKey.hasNext()) {
        return false;
      }
      Entry<String, Set<String>> currentEntry = byKey.next();
      currentKey = currentEntry.getKey();
      currentValues = currentEntry.getValue().iterator();
      return hasNext();
    }

    @Override
    public Entry<String, String> next() {
      if (!hasNext()) {
        throw new NoSuchElementException();
      }
      String k = currentKey, v = currentValues.next();
      return new SimpleImmutableEntry<String, String>(k, v);
    }

    /** Not supported. */
    @Override
    public void remove() {
      throw new UnsupportedOperationException();
    }
  }

  /** True if exactly the same key-values are represented. */
  @Override
  public boolean equals(Object o) {
    if (!(o instanceof Metadata)) {
      return false;
    }
    if (this == o) {
      return true;
    }
    Metadata other = (Metadata) o;
    return mappings.equals(other.mappings);
  }

  @Override
  public int hashCode() {
    return mappings.hashCode();
  }

  /** True with 0 entries. */
  public boolean isEmpty() {
    return mappings.isEmpty();
  }

  /** Contains every key and value pair; useful for debugging. */
  public String toString() {
    String sep = ", ";
    StringBuilder builder = new StringBuilder();
    for (Entry<String, String> e : this) {
      builder.append(sep);
      builder.append(e.getKey()).append("=").append(e.getValue());
    }
    String body = "";
    if (0 != builder.length()) {
      body = builder.substring(sep.length());
    }
    return "[" + body + "]";
  }

  /** Does not allow any mutating operations. */
  private static class ReadableMetadata extends Metadata {
    @Override
    public void set(String k, String v) {
      throw new UnsupportedOperationException();
    }

    @Override
    public void set(String k, Set<String> v) {
      throw new UnsupportedOperationException();
    }

    @Override
    public void add(String k, String v) {
      throw new UnsupportedOperationException();
    }

    @Override
    public void set(Iterable<Entry<String, String>> it) {
      throw new UnsupportedOperationException();
    }
    
    @Override
    public Set<String> getKeys() {
      return Collections.unmodifiableSet(super.getKeys());
    }
  };

  /** Get a reference to an unmodifiable view of this object. */
  public Metadata unmodifiableView() {
    Metadata unmodifiable = new ReadableMetadata();
    // Extra precaution against mappings use, but not against moding
    // sets that are values inside it.
    unmodifiable.mappings = Collections.unmodifiableMap(this.mappings); 
    return unmodifiable;
  }
}
