/*
 * Copyright (c) 2007-2013, 2015 Eike Stepper (Berlin, Germany) and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Eike Stepper - initial API and implementation
 *    Simon McDuff - bug 201266
 *    Simon McDuff - bug 202725
 *    Christian W. Damus (CEA LIST) - bug 399306
 *    Christian W. Damus (CEA LIST) - bug 418454
 */
package org.eclipse.emf.cdo.internal.server;

import org.eclipse.emf.cdo.common.CDOCommonRepository;
import org.eclipse.emf.cdo.common.CDOCommonSession;
import org.eclipse.emf.cdo.common.CDOCommonSession.Options.LockNotificationMode;
import org.eclipse.emf.cdo.common.branch.CDOBranchChangedEvent.ChangeKind;
import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo;
import org.eclipse.emf.cdo.common.protocol.CDOProtocol.CommitNotificationInfo;
import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
import org.eclipse.emf.cdo.internal.server.bundle.OM;
import org.eclipse.emf.cdo.server.IPermissionManager;
import org.eclipse.emf.cdo.server.ISession;
import org.eclipse.emf.cdo.session.remote.CDORemoteSessionMessage;
import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch;
import org.eclipse.emf.cdo.spi.server.IAuthenticationProtocol;
import org.eclipse.emf.cdo.spi.server.ISessionProtocol;
import org.eclipse.emf.cdo.spi.server.InternalRepository;
import org.eclipse.emf.cdo.spi.server.InternalSession;
import org.eclipse.emf.cdo.spi.server.InternalSessionManager;

import org.eclipse.net4j.util.ObjectUtil;
import org.eclipse.net4j.util.container.Container;
import org.eclipse.net4j.util.io.ExtendedDataInputStream;
import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
import org.eclipse.net4j.util.om.trace.ContextTracer;
import org.eclipse.net4j.util.security.CredentialsUpdateOperation;
import org.eclipse.net4j.util.security.DiffieHellman;
import org.eclipse.net4j.util.security.DiffieHellman.Client.Response;
import org.eclipse.net4j.util.security.DiffieHellman.Server.Challenge;
import org.eclipse.net4j.util.security.IAuthenticator;
import org.eclipse.net4j.util.security.IAuthenticator2;
import org.eclipse.net4j.util.security.IUserManager;
import org.eclipse.net4j.util.security.UserManagerAuthenticator;

import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author Eike Stepper
 */
public class SessionManager extends Container<ISession>implements InternalSessionManager
{
  private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_SESSION, SessionManager.class);

  private InternalRepository repository;

  private DiffieHellman.Server authenticationServer;

  private IAuthenticator authenticator;

  private IPermissionManager permissionManager;

  private final Map<Integer, InternalSession> sessions = new HashMap<Integer, InternalSession>();

  private final AtomicInteger lastSessionID = new AtomicInteger();

  /**
   * @since 2.0
   */
  public SessionManager()
  {
  }

  /**
   * @since 2.0
   */
  public InternalRepository getRepository()
  {
    return repository;
  }

  /**
   * @since 2.0
   */
  public void setRepository(InternalRepository repository)
  {
    checkInactive();
    this.repository = repository;
  }

  @Deprecated
  public IUserManager getUserManager()
  {
    if (authenticator instanceof UserManagerAuthenticator)
    {
      return ((UserManagerAuthenticator)authenticator).getUserManager();
    }

    return null;
  }

  @Deprecated
  public void setUserManager(IUserManager userManager)
  {
    UserManagerAuthenticator userManagerAuthenticator = new UserManagerAuthenticator();
    userManagerAuthenticator.setUserManager(userManager);

    setAuthenticator(userManagerAuthenticator);
  }

  public DiffieHellman.Server getAuthenticationServer()
  {
    return authenticationServer;
  }

  public void setAuthenticationServer(DiffieHellman.Server authenticationServer)
  {
    this.authenticationServer = authenticationServer;
  }

  public IAuthenticator getAuthenticator()
  {
    return authenticator;
  }

  public void setAuthenticator(IAuthenticator authenticator)
  {
    this.authenticator = authenticator;
    if (isActive() && authenticator != null)
    {
      initAuthentication();
    }
  }

  public IPermissionManager getPermissionManager()
  {
    return permissionManager;
  }

  public void setPermissionManager(IPermissionManager permissionManager)
  {
    this.permissionManager = permissionManager;
  }

  public InternalSession[] getSessions()
  {
    synchronized (sessions)
    {
      return sessions.values().toArray(new InternalSession[sessions.size()]);
    }
  }

  /**
   * @since 2.0
   */
  public InternalSession getSession(int sessionID)
  {
    checkActive();
    synchronized (sessions)
    {
      return sessions.get(sessionID);
    }
  }

  public InternalSession[] getElements()
  {
    return getSessions();
  }

  @Override
  public boolean isEmpty()
  {
    synchronized (sessions)
    {
      return sessions.isEmpty();
    }
  }

  /**
   * @since 2.0
   */
  public InternalSession openSession(ISessionProtocol sessionProtocol)
  {
    int id = lastSessionID.incrementAndGet();
    if (TRACER.isEnabled())
    {
      TRACER.trace("Opening session " + id); //$NON-NLS-1$
    }

    String userID = authenticateUser(sessionProtocol);
    InternalSession session = createSession(id, userID, sessionProtocol);
    LifecycleUtil.activate(session);

    synchronized (sessions)
    {
      sessions.put(id, session);
    }

    fireElementAddedEvent(session);
    sendRemoteSessionNotification(session, CDOProtocolConstants.REMOTE_SESSION_OPENED);
    return session;
  }

  protected InternalSession createSession(int id, String userID, ISessionProtocol protocol)
  {
    return new Session(this, protocol, id, userID);
  }

  public void sessionClosed(InternalSession session)
  {
    int sessionID = session.getSessionID();
    InternalSession removeSession = null;
    synchronized (sessions)
    {
      removeSession = sessions.remove(sessionID);
    }

    if (removeSession != null)
    {
      fireElementRemovedEvent(session);
      sendRemoteSessionNotification(session, CDOProtocolConstants.REMOTE_SESSION_CLOSED);
    }
  }

  public void sendRepositoryTypeNotification(CDOCommonRepository.Type oldType, CDOCommonRepository.Type newType)
  {
    for (InternalSession session : getSessions())
    {
      try
      {
        session.sendRepositoryTypeNotification(oldType, newType);
      }
      catch (Exception ex)
      {
        handleNotificationProblem(session, ex);
      }
    }
  }

  @Deprecated
  public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState)
  {
    sendRepositoryStateNotification(oldState, newState, null);
  }

  public void sendRepositoryStateNotification(CDOCommonRepository.State oldState, CDOCommonRepository.State newState,
      CDOID rootResourceID)
  {
    for (InternalSession session : getSessions())
    {
      try
      {
        session.sendRepositoryStateNotification(oldState, newState, rootResourceID);
      }
      catch (Exception ex)
      {
        handleNotificationProblem(session, ex);
      }
    }
  }

  @Deprecated
  public void sendBranchNotification(InternalSession sender, InternalCDOBranch branch)
  {
    sendBranchNotification(sender, branch, ChangeKind.CREATED);
  }

  public void sendBranchNotification(InternalSession sender, InternalCDOBranch branch, ChangeKind changeKind)
  {
    for (InternalSession session : getSessions())
    {
      if (session != sender)
      {
        try
        {
          session.sendBranchNotification(branch, changeKind);
        }
        catch (Exception ex)
        {
          handleNotificationProblem(session, ex);
        }
      }
    }
  }

  @Deprecated
  public void sendCommitNotification(InternalSession sender, CDOCommitInfo commitInfo)
  {
    throw new UnsupportedOperationException();
  }

  @Deprecated
  public void sendCommitNotification(InternalSession sender, CDOCommitInfo commitInfo, boolean clearResourcePathCache)
  {
    throw new UnsupportedOperationException();
  }

  public void sendCommitNotification(CommitNotificationInfo info)
  {
    CDOCommonSession sender = info.getSender();
    for (InternalSession session : getSessions())
    {
      if (session != sender)
      {
        try
        {
          session.sendCommitNotification(info);
        }
        catch (Exception ex)
        {
          handleNotificationProblem(session, ex);
        }
      }
    }
  }

  public void sendLockNotification(InternalSession sender, CDOLockChangeInfo lockChangeInfo)
  {
    for (InternalSession session : getSessions())
    {
      if (session == sender || session.options().getLockNotificationMode() == LockNotificationMode.OFF)
      {
        continue;
      }

      try
      {
        session.sendLockNotification(lockChangeInfo);
      }
      catch (Exception ex)
      {
        handleNotificationProblem(session, ex);
      }
    }
  }

  /**
   * @since 2.0
   */
  public void sendRemoteSessionNotification(InternalSession sender, byte opcode)
  {
    try
    {
      for (InternalSession session : getSessions())
      {
        if (session != sender && session.isSubscribed())
        {
          try
          {
            session.sendRemoteSessionNotification(sender, opcode);
          }
          catch (Exception ex)
          {
            handleNotificationProblem(session, ex);
          }
        }
      }
    }
    catch (Exception ex)
    {
      OM.LOG.warn("A problem occured while notifying other sessions", ex);
    }
  }

  public List<Integer> sendRemoteMessageNotification(InternalSession sender, CDORemoteSessionMessage message,
      int[] recipients)
  {
    List<Integer> result = new ArrayList<Integer>();
    for (int i = 0; i < recipients.length; i++)
    {
      InternalSession recipient = getSession(recipients[i]);

      try
      {
        if (recipient != null && recipient.isSubscribed())
        {
          recipient.sendRemoteMessageNotification(sender, message);
          result.add(recipient.getSessionID());
        }
      }
      catch (Exception ex)
      {
        handleNotificationProblem(recipient, ex);
      }
    }

    return result;
  }

  protected void handleNotificationProblem(InternalSession session, Throwable t)
  {
    OM.LOG.warn("A problem occured while notifying session " + session, t);
  }

  public String authenticateUser(IAuthenticationProtocol protocol) throws SecurityException
  {
    if (protocol == null)
    {
      return null;
    }

    if (authenticationServer == null || authenticator == null)
    {
      return null;
    }

    try
    {
      Challenge challenge = authenticationServer.getChallenge();
      Response response = protocol.sendAuthenticationChallenge(challenge);
      if (response == null)
      {
        throw notAuthenticated();
      }

      ByteArrayInputStream bais = new ByteArrayInputStream(authenticationServer.handleResponse(response));

      @SuppressWarnings("resource")
      ExtendedDataInputStream stream = new ExtendedDataInputStream(bais);
      String userID = stream.readString();
      char[] password = stream.readString().toCharArray();

      authenticator.authenticate(userID, password);
      return userID;
    }
    catch (SecurityException ex)
    {
      throw ex;
    }
    catch (Exception ex)
    {
      Throwable cause = ex.getCause();
      if (cause instanceof SecurityException)
      {
        throw (SecurityException)cause;
      }

      throw new SecurityException(ex);
    }
  }

  public void changeUserCredentials(IAuthenticationProtocol sessionProtocol, String userID)
  {
    changeUserCredentials(sessionProtocol, userID, CredentialsUpdateOperation.CHANGE_PASSWORD);
  }

  public void resetUserCredentials(IAuthenticationProtocol sessionProtocol, String userID)
  {
    changeUserCredentials(sessionProtocol, userID, CredentialsUpdateOperation.RESET_PASSWORD);
  }

  protected void changeUserCredentials(IAuthenticationProtocol sessionProtocol, String userID,
      CredentialsUpdateOperation operation)
  {

    if (sessionProtocol == null)
    {
      return;
    }

    if (authenticationServer == null || authenticator == null)
    {
      return;
    }

    if (!(authenticator instanceof IAuthenticator2))
    {
      throw new SecurityException("Current authenticator does not permit password updates"); //$NON-NLS-1$
    }

    try
    {
      Challenge challenge = authenticationServer.getChallenge();
      Response response = sessionProtocol.sendCredentialsChallenge(challenge, userID, operation);
      if (response == null)
      {
        throw notAuthenticated();
      }

      ByteArrayInputStream baos = new ByteArrayInputStream(authenticationServer.handleResponse(response));
      @SuppressWarnings("resource")
      ExtendedDataInputStream stream = new ExtendedDataInputStream(baos);

      if (operation == CredentialsUpdateOperation.RESET_PASSWORD)
      {
        String adminID = stream.readString();
        char[] adminPassword = stream.readString().toCharArray();
        if (!ObjectUtil.equals(userID, stream.readString()))
        {
          throw new SecurityException("Attempt to reset password of a different user than requested"); //$NON-NLS-1$
        }
        char[] newPassword = stream.readString().toCharArray();

        // this will throw if the current credentials are not authenticated as an administrator
        ((IAuthenticator2)authenticator).resetPassword(adminID, adminPassword, userID, newPassword);
      }
      else
      {
        userID = stream.readString(); // user can change any password that she can authenticate on the old password
        char[] password = stream.readString().toCharArray();
        char[] newPassword = stream.readString().toCharArray();

        // this will throw if the "old password" provided by the user is not correct
        ((IAuthenticator2)authenticator).updatePassword(userID, password, newPassword);
      }
    }
    catch (SecurityException ex)
    {
      throw ex;
    }
    catch (Exception ex)
    {
      Throwable cause = ex.getCause();
      if (cause instanceof SecurityException)
      {
        throw (SecurityException)cause;
      }

      throw new SecurityException(ex);
    }
  }

  @Override
  protected void doActivate() throws Exception
  {
    super.doActivate();
    initAuthentication();
  }

  protected void initAuthentication()
  {
    if (authenticator != null)
    {
      if (authenticationServer == null)
      {
        authenticationServer = new DiffieHellman.Server(repository.getUUID());
      }

      LifecycleUtil.activate(authenticationServer);
      LifecycleUtil.activate(authenticator);
    }
  }

  @Override
  protected void doDeactivate() throws Exception
  {
    LifecycleUtil.deactivate(authenticator);
    LifecycleUtil.deactivate(authenticationServer);

    for (InternalSession session : getSessions())
    {
      LifecycleUtil.deactivate(session);
    }

    super.doDeactivate();
  }

  @SuppressWarnings("deprecation")
  private SecurityException notAuthenticated()
  {
    // Existing clients may expect this deprecated exception type
    return new org.eclipse.emf.cdo.common.util.NotAuthenticatedException();
  }
}
