// Copyright 2013 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.ad;

import com.google.common.annotations.VisibleForTesting;

import java.io.*;
import java.util.*;

import javax.naming.*;
import javax.naming.directory.*;
import javax.naming.ldap.Control;
import javax.naming.ldap.InitialLdapContext;

/**
 * Mock of {@link LdapContext}.
 */
public class MockLdapContext extends InitialLdapContext {
  private BasicAttributes attributes = new BasicAttributes();
  private Hashtable<String, Object> searchResults
      = new Hashtable<String, Object>();
  @VisibleForTesting
  Control[] controls = new Control[0];

  public MockLdapContext() throws NamingException {
  }

  @Override
  public Attributes getAttributes(String name) throws NamingException {
    return attributes;
  }

  /** Normal way to add things to this Mock */
  public MockLdapContext addKey(String key, Object value) {
    attributes.put(key, value);
    return this;
  }

  public MockLdapContext removeKey(String key) {
    attributes.remove(key);
    return this;
  }

  public static String makeKey(String filter, String attribute, String baseDn) {
    return filter + "|" + attribute + "|" + baseDn;
  }

  public MockLdapContext addSearchResult(String filter,
      String attribute, String baseDn, Object value) {
    searchResults.put(makeKey(filter, attribute, baseDn), value);
    return this;
  }

  /** Returns a <code>NamingEnumeration</code> of <code>SearchResult</code>s */
  public NamingEnumeration<SearchResult> search(String base, String filter,
      SearchControls searchControls) throws NamingException {
    Vector<SearchResult> results = new Vector<SearchResult>();
    SearchResult currentResult = null;
    for (String attribute : searchControls.getReturningAttributes()) {
      Object o = searchResults.get(makeKey(filter, attribute, base));
      if (o == null) {
        // hack to make search for member;Range=X-Y succeed when that's the
        // final range present
        if (attribute.startsWith("member;Range=")) {
          attribute += "*";
          o = searchResults.get(makeKey(filter, attribute, base));
        }
      }
      if (o != null) {
        if (currentResult == null) {
          currentResult = makeSearchResult(attribute, o, base);
          results.add(currentResult);
        } else {
          Attributes attrs = currentResult.getAttributes();
          this.addAttribute(attrs, attribute, o);
          currentResult.setAttributes(attrs);
        }
      }
    }
    return new SearchResultsNamingEnumeration(results);
  }

  /** properly handle collections as we add a new attribute */
  private static void addAttribute(Attributes attrs, String newAttr,
      Object value) {
    attrs.put(newAttr, value);
    if (value instanceof Collection<?>) {
      Attribute attr = attrs.get(newAttr);
      attr.clear();
      for (Object member: (Collection<?>) value) {
        attr.add(member);
      }
    }
  }

  /** Creates a <code>SearchResults</code> wrapper with a single attribute */
  private static SearchResult makeSearchResult(String attribute, Object o,
      String baseDn) {
    SearchResult sr = new SearchResult("search result name", o,
        new BasicAttributes());
    addAttribute(sr.getAttributes(), attribute, o);
    sr.setNameInNamespace("cn=name\\ under," + baseDn);
    return sr;
  }

  @Override
  public Control[] getResponseControls() throws NamingException {
    return controls;
  };

  /** Sets the controls (which this class does nothing with) */
  @Override
  public void setRequestControls(Control[] requestControls)
      throws NamingException {
    controls = requestControls;
  };

  @VisibleForTesting
  static class SearchResultsNamingEnumeration
      implements NamingEnumeration<SearchResult> {
    private final Enumeration<SearchResult> results;
    private SearchResult nextElement = null;

    SearchResultsNamingEnumeration(Vector<SearchResult> results) {
      this.results = results.elements();
    }

    private SearchResult getNextElement() {
      if (results.hasMoreElements()) {
        return results.nextElement();
      }
      return null;
    }

    public boolean hasMore() {
      if (nextElement != null) {
        return true;
      }
      nextElement = getNextElement();
      return (nextElement != null);
    }

    public boolean hasMoreElements() {
      return hasMore();
    }

    public SearchResult next() {
      if (!hasMore()) {
        throw new NoSuchElementException();
      }
      SearchResult res = nextElement;
      nextElement = null;
      return res;
    }

    public SearchResult nextElement() {
      return next();
    }

    public void close() {
    }
  }
}
