/*
 * 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.geode.internal.cache.tier.sockets;

import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.logging.log4j.Logger;
import org.apache.shiro.subject.Subject;

import org.apache.geode.annotations.VisibleForTesting;
import org.apache.geode.internal.security.AuthorizeRequest;
import org.apache.geode.internal.security.AuthorizeRequestPP;
import org.apache.geode.logging.internal.log4j.api.LogService;

public class ClientUserAuths {
  private static final Logger logger = LogService.getLogger();
  // private AtomicLong counter = new AtomicLong(1);
  private Random uniqueIdGenerator = null;
  private int m_seed;
  private long m_firstId;

  private ConcurrentHashMap<Long, UserAuthAttributes> uniqueIdVsUserAuth =
      new ConcurrentHashMap<Long, UserAuthAttributes>();
  private ConcurrentHashMap<String, UserAuthAttributes> cqNameVsUserAuth =
      new ConcurrentHashMap<String, UserAuthAttributes>();
  private ConcurrentHashMap<Long, Subject> uniqueIdVsSubject =
      new ConcurrentHashMap<Long, Subject>();

  public long putUserAuth(UserAuthAttributes userAuthAttr) {
    // TODO:hitesh should we do random here
    // long newId = counter.getAndIncrement();
    long newId = getNextID();
    uniqueIdVsUserAuth.put(newId, userAuthAttr);
    return newId;
  }

  public long putSubject(Subject subject) {
    long newId = getNextID();
    uniqueIdVsSubject.put(newId, subject);
    logger.debug("Subject of {} added.", newId);
    return newId;
  }

  public ClientUserAuths(int clientProxyHashcode) {
    m_seed = clientProxyHashcode;
    uniqueIdGenerator = new Random(m_seed + System.currentTimeMillis());
    m_firstId = uniqueIdGenerator.nextLong();
  }

  private synchronized long getNextID() {
    long uniqueId = uniqueIdGenerator.nextLong();
    if (uniqueId == m_firstId) {
      uniqueIdGenerator = new Random(m_seed + System.currentTimeMillis());
      m_firstId = uniqueIdGenerator.nextLong();
      // now every user need to reauthenticate as we are short of Ids..
      // though possibility of this is rare.
      uniqueIdVsUserAuth.clear();
      return m_firstId;
    }
    return uniqueId;
  }

  public UserAuthAttributes getUserAuthAttributes(long userId) {
    return uniqueIdVsUserAuth.get(userId);
  }

  @VisibleForTesting
  protected Collection<Subject> getSubjects() {
    return Collections.unmodifiableCollection(this.uniqueIdVsSubject.values());
  }

  public Subject getSubject(long userId) {
    return uniqueIdVsSubject.get(userId);
  }

  public boolean removeSubject(long userId) {
    Subject subject = uniqueIdVsSubject.remove(userId);
    logger.debug("Subject of {} removed.", userId);
    if (subject == null)
      return false;

    subject.logout();
    return true;
  }

  public UserAuthAttributes getUserAuthAttributes(String cqName) {
    // Long uniqueId = cqNameVsUserAuth.get(cqName);
    // return uniqueIdVsUserAuth.get(uniqueId);
    return cqNameVsUserAuth.get(cqName);
  }

  public void setUserAuthAttributesForCq(String cqName, long uniqueId, boolean isDurable) {
    UserAuthAttributes uaa = this.uniqueIdVsUserAuth.get(uniqueId);

    if (uaa != null) {
      if (!isDurable)
        this.cqNameVsUserAuth.put(cqName, uaa);
      else {
        UserAuthAttributes oldUaa = this.cqNameVsUserAuth.put(cqName, uaa);
        if (oldUaa != null) {
          if (oldUaa != uaa)// clean earlier one
          {
            this.cleanUserAuth(oldUaa);
            // add durable(increment)
            uaa.setDurable();
          } else {
            // if looks extra call from client
          }
        } else {
          uaa.setDurable();
        }
      }
    }
  }

  public void removeUserAuthAttributesForCq(String cqName, boolean isDurable) {
    UserAuthAttributes uaa = this.cqNameVsUserAuth.remove(cqName);
    if (uaa != null && isDurable)
      uaa.unsetDurable();
  }

  public boolean removeUserId(long userId, boolean keepAlive) {
    UserAuthAttributes uaa = uniqueIdVsUserAuth.get(userId);
    if (uaa != null && !(uaa.isDurable() && keepAlive)) {
      uaa = uniqueIdVsUserAuth.remove(userId);
      logger.debug("UserAuth of {} removed.");
      if (uaa != null) {
        cleanUserAuth(uaa);
        return true;
      }
    }
    return false;
  }



  public void cleanUserAuth(UserAuthAttributes userAuth) {
    if (userAuth != null) {
      AuthorizeRequest authReq = userAuth.getAuthzRequest();
      try {
        if (authReq != null) {
          authReq.close();
          authReq = null;
        }
      } catch (Exception ex) {
        // TODO:hitesh
        /*
         * if (securityLogger.warningEnabled()) { securityLogger.warning( LocalizedStrings.
         * String.
         * format("%s: An exception was thrown while closing client authorization callback. %s",
         * new Object[] {"", ex})); }
         */
      }
      try {
        AuthorizeRequestPP postAuthzReq = userAuth.getPostAuthzRequest();
        if (postAuthzReq != null) {
          postAuthzReq.close();
          postAuthzReq = null;
        }
      } catch (Exception ex) {
        // TODO:hitesh
        /*
         * if (securityLogger.warningEnabled()) { securityLogger.warning( LocalizedStrings.
         * String.
         * format("%s: An exception was thrown while closing client post-process authorization callback. %s"
         * ,
         * new Object[] {"", ex})); }
         */
      }
    }

  }

  public void cleanup(boolean fromCacheClientProxy) {
    for (UserAuthAttributes userAuth : this.uniqueIdVsUserAuth.values()) {
      // isDurable is checked for multiuser in CQ
      if (!fromCacheClientProxy && !userAuth.isDurable()) {// from serverConnection class
        cleanUserAuth(userAuth);
      } else if (fromCacheClientProxy && userAuth.isDurable()) {// from cacheclientProxy class
        cleanUserAuth(userAuth);
      }
    }

    // Logout the subjects
    for (Long subjectId : uniqueIdVsSubject.keySet()) {
      removeSubject(subjectId);
    }
  }

  public void fillPreviousCQAuth(ClientUserAuths previousClientUserAuths) {
    for (Iterator<Map.Entry<String, UserAuthAttributes>> iter =
        previousClientUserAuths.cqNameVsUserAuth.entrySet().iterator(); iter.hasNext();) {
      Map.Entry<String, UserAuthAttributes> ent = iter.next();
      String cqName = ent.getKey();
      UserAuthAttributes prevUaa = ent.getValue();
      UserAuthAttributes newUaa = this.cqNameVsUserAuth.putIfAbsent(cqName, prevUaa);

      if (newUaa != null) {
        previousClientUserAuths.cleanUserAuth(prevUaa);
      }
    }
  }
}
