// Copyright 2011 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 adaptorlib;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

/** Keeps set of MetaItem instanes after validation. */
public final class Metadata implements Iterable<MetaItem> {
  /** Object instance to denote documents that have been deleted. */
  public static final Metadata DELETED
      = new Metadata(Collections.<MetaItem>emptySet());
  /** Empty convenience instance. */
  public static final Metadata EMPTY
      = new Metadata(Collections.<MetaItem>emptySet());

  private final Set<MetaItem> items;
 
  /**
   * Validates that each meta name is unique, there is either
   * public-indicator or ACLs and that ACLs values are acceptable.
   */ 
  public Metadata(Set<MetaItem> allMeta) {
    items = Collections.unmodifiableSet(new TreeSet<MetaItem>(allMeta));
    checkConsistency(items, toMap());
  }

  @Override
  public boolean equals(Object o) {
    if (this == DELETED || o == DELETED) {
      return this == o;
    }
    boolean same = false;
    if (null != o && this.getClass().equals(o.getClass())) {
      Metadata other = (Metadata) o;
      same = items.equals(other.items);
    } 
    return same;
  }

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

  @Override
  public Iterator<MetaItem> iterator() {
    return items.iterator();
  }

  @Override
  public String toString() {
    return items.toString();
  }

  public Map<String, String> toMap() {
    Map<String, String> map = new HashMap<String, String>();
    for (MetaItem item : this) {
      map.put(item.getName(), item.getValue());
    }
    return map;
  }

  private static void checkConsistency(Set<MetaItem> items,
                                       Map<String, String> allMeta) {
    checkEachNameIsUnique(items); 
    checkNandPublicAndAcls(allMeta);
    checkBothOrNoneAcls(allMeta); 
    checkPublicIsBoolean(allMeta); 
  }

  /** Each MetaItem name needs be unique. */
  private static void checkEachNameIsUnique(Set<MetaItem> m) {
    HashSet<String> unique = new HashSet<String>();
    HashSet<String> dup = new HashSet<String>();
    for (MetaItem item : m) {
      String name = item.getName();
      if (unique.contains(name)) {
        dup.add(name);
      } else {
        unique.add(name);
      }
    }
    if (0 < dup.size()) {
      throw new IllegalArgumentException("duplicate names: " + dup);
    }
  }

  /** Either have public indicator or ACLs, but not both. */
  private static void checkNandPublicAndAcls(Map<String, String> m) {
    boolean hasPublicName = m.containsKey("google:ispublic");
    boolean hasAcls = m.containsKey("google:aclusers")
        || m.containsKey("google:aclgroups");
    if (hasPublicName && hasAcls) {
      throw new IllegalArgumentException("has both ispublic and ACLs");
    }
  }

  /** Cannot provide users without groups and vice-versa. */
  private static void checkBothOrNoneAcls(Map<String, String> m) {
    boolean hasUserAcls = m.containsKey("google:aclusers");
    boolean hasGroupAcls = m.containsKey("google:aclgroups");
    if (hasUserAcls && !hasGroupAcls) {
      throw new IllegalArgumentException("has users, but not groups");
    } else if (hasGroupAcls && !hasUserAcls) {
      throw new IllegalArgumentException("has groups, but not users");
    } else if (hasGroupAcls && hasUserAcls) {
      String userLine = m.get("google:aclusers").trim();
      String groupLine = m.get("google:aclgroups").trim();
      if (userLine.isEmpty() && groupLine.isEmpty()) {
        throw new IllegalArgumentException("both users and groups empty");
      }
    }
  }

  /** If has public indicator value is acceptable. */
  private static void checkPublicIsBoolean(Map<String, String> m) {
    String value = m.get("google:ispublic");
    if (null != value) {
      if (!"true".equals(value) && !"false".equals(value)) {
        throw new IllegalArgumentException("ispublic is not true nor false");
      }
    }
  }
}
