// Copyright (C) 2009 The Android Open Source Project
//
// 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.gerrit.auth.ldap;

import com.google.gerrit.common.data.ParameterizedString;
import com.google.gerrit.metrics.Timer0;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.PartialResultException;
import javax.naming.directory.Attribute;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

/** Supports issuing parameterized queries against an LDAP data source. */
class LdapQuery {
  static final Set<String> ALL_ATTRIBUTES = null;

  private final String base;
  private final SearchScope searchScope;
  private final ParameterizedString pattern;
  private final String[] returnAttributes;

  LdapQuery(
      final String base,
      final SearchScope searchScope,
      final ParameterizedString pattern,
      final Set<String> returnAttributes) {
    this.base = base;
    this.searchScope = searchScope;

    this.pattern = pattern;

    if (returnAttributes != null) {
      this.returnAttributes = new String[returnAttributes.size()];
      returnAttributes.toArray(this.returnAttributes);
    } else {
      this.returnAttributes = null;
    }
  }

  List<String> getParameters() {
    return pattern.getParameterNames();
  }

  List<Result> query(DirContext ctx, Map<String, String> params, Timer0 queryTimer)
      throws NamingException {
    final SearchControls sc = new SearchControls();
    final NamingEnumeration<SearchResult> res;

    sc.setSearchScope(searchScope.scope());
    sc.setReturningAttributes(returnAttributes);
    try (Timer0.Context ignored = queryTimer.start()) {
      res = ctx.search(base, pattern.getRawPattern(), pattern.bind(params), sc);
    }
    try {
      final List<Result> r = new ArrayList<>();
      try {
        while (res.hasMore()) {
          r.add(new Result(res.next()));
        }
      } catch (PartialResultException e) {
        // Ignored
      }
      return r;
    } finally {
      res.close();
    }
  }

  class Result {
    private final Map<String, Attribute> atts = new HashMap<>();

    Result(SearchResult sr) {
      if (returnAttributes != null) {
        for (String attName : returnAttributes) {
          final Attribute a = sr.getAttributes().get(attName);
          if (a != null && a.size() > 0) {
            atts.put(attName, a);
          }
        }

      } else {
        NamingEnumeration<? extends Attribute> e = sr.getAttributes().getAll();
        while (e.hasMoreElements()) {
          final Attribute a = e.nextElement();
          atts.put(a.getID(), a);
        }
      }

      atts.put("dn", new BasicAttribute("dn", sr.getNameInNamespace()));
    }

    String getDN() throws NamingException {
      return get("dn");
    }

    String get(String attName) throws NamingException {
      final Attribute att = getAll(attName);
      return att != null && 0 < att.size() ? String.valueOf(att.get(0)) : null;
    }

    Attribute getAll(String attName) {
      return atts.get(attName);
    }

    Set<String> attributes() {
      return Collections.unmodifiableSet(atts.keySet());
    }

    @Override
    public String toString() {
      try {
        return getDN();
      } catch (NamingException e) {
        return "";
      }
    }
  }
}
