/*
 * Copyright (c) 2011, 2012 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
 */
package org.eclipse.emf.cdo.common.lock;

import org.eclipse.emf.cdo.common.CDOCommonRepository;
import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
import org.eclipse.emf.cdo.common.id.CDOID;

import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;

import java.util.Map;

/**
 * Manages all persistent aspects of durable CDO views such as {@link CDOBranchPoint branch point} and acquired locks.
 *
 * @author Eike Stepper
 * @since 4.0
 * @apiviz.uses {@link IDurableLockingManager.LockArea} - - manages
 */
public interface IDurableLockingManager
{
  public LockArea createLockArea(String userID, CDOBranchPoint branchPoint, boolean readOnly,
      Map<CDOID, LockGrade> locks) throws LockAreaAlreadyExistsException;

  /**
   * Returns the {@link LockArea lock area} specified by the given durableLockingID, never <code>null</code>.
   *
   * @throws LockAreaNotFoundException
   *           if the given durableLockingID is unknown.
   */
  public LockArea getLockArea(String durableLockingID) throws LockAreaNotFoundException;

  public void getLockAreas(String userIDPrefix, LockArea.Handler handler);

  public void deleteLockArea(String durableLockingID);

  /**
   * Encapsulates the persistable information about a single durable CDO view like {@link CDOBranchPoint branch point}
   * and acquired locks.
   *
   * @author Eike Stepper
   * @noextend This interface is not intended to be extended by clients.
   * @noimplement This interface is not intended to be implemented by clients.
   * @apiviz.composedOf {@link IDurableLockingManager.LockGrade} - - locks
   */
  public interface LockArea extends CDOBranchPoint
  {
    /**
     * @since 4.1
     */
    public static final int DEFAULT_DURABLE_LOCKING_ID_BYTES = 32;

    public String getDurableLockingID();

    public String getUserID();

    public boolean isReadOnly();

    public Map<CDOID, LockGrade> getLocks();

    /**
     * Returns <code>true</code> if this instance represents a lock area that is known to be missing (not present) on a
     * master server. (Relevant only in a replicating configuration.)
     *
     * @since 4.1
     */
    public boolean isMissing();

    /**
     * A call-back interface for <em>handling</em> {@link LockArea lock area} objects.
     *
     * @author Eike Stepper
     * @apiviz.uses {@link IDurableLockingManager.LockArea} - - handles
     */
    public interface Handler
    {
      public boolean handleLockArea(LockArea area);
    }
  }

  /**
   * Thrown if a {@link LockArea lock area} is spcified that does not exist in a CDO {@link CDOCommonRepository
   * repository}.
   *
   * @author Eike Stepper
   */
  public static class LockAreaNotFoundException extends IllegalStateException
  {
    private static final long serialVersionUID = 1L;

    private String durableLockingID;

    public LockAreaNotFoundException(String durableLockingID)
    {
      super("No lock area for ID=" + durableLockingID);
      this.durableLockingID = durableLockingID;
    }

    public LockAreaNotFoundException(String message, Throwable cause, String durableLockingID)
    {
      super(message, cause);
      this.durableLockingID = durableLockingID;
    }

    public String getDurableLockingID()
    {
      return durableLockingID;
    }
  }

  /**
   * Exception occurs when attempting to create a durable {@link LockArea} that already exists.
   *
   * @author Caspar De Groot
   * @since 4.1
   */
  public static class LockAreaAlreadyExistsException extends IllegalStateException
  {
    private static final long serialVersionUID = 1L;

    private String durableLockingID;

    public LockAreaAlreadyExistsException(String durableLockingID)
    {
      super("A lock area with ID=" + durableLockingID + " already exists");
      this.durableLockingID = durableLockingID;
    }

    public String getDurableLockingID()
    {
      return durableLockingID;
    }
  }

  /**
   * Enumerates the possible combinations of read and write locks on a single CDO object.
   *
   * @author Eike Stepper
   * @noextend This interface is not intended to be extended by clients.
   */
  public enum LockGrade
  {
    NONE(0), READ(1), WRITE(2), READ_WRITE(READ.getValue() | WRITE.getValue()),

    /**
     * @since 4.1
     */
    OPTION(4),

    /**
     * @since 4.1
     */
    READ_OPTION(READ.getValue() | OPTION.getValue()),

    /**
     * @since 4.1
     */
    WRITE_OPTION(WRITE.getValue() | OPTION.getValue()),

    /**
     * @since 4.1
     */
    READ_WRITE_OPTION(READ.getValue() | WRITE.getValue() | OPTION.getValue());

    private final int value;

    private LockGrade(int value)
    {
      this.value = value;
    }

    public int getValue()
    {
      return value;
    }

    public boolean isRead()
    {
      return (value & 1) != 0;
    }

    public boolean isWrite()
    {
      return (value & 2) != 0;
    }

    /**
     * @since 4.1
     */
    public boolean isOption()
    {
      return (value & 4) != 0;
    }

    public LockGrade getUpdated(LockType type, boolean on)
    {
      int mask = getMask(type);

      if (on)
      {
        return get(value | mask);
      }

      return get(value & ~mask);
    }

    private int getMask(LockType type)
    {
      switch (type)
      {
      case READ:
        return 1;

      case WRITE:
        return 2;

      case OPTION:
        return 4;
      }

      return 0;
    }

    public static LockGrade get(LockType type)
    {
      if (type == LockType.READ)
      {
        return READ;
      }

      if (type == LockType.WRITE)
      {
        return WRITE;
      }

      if (type == LockType.OPTION)
      {
        return OPTION;
      }

      return NONE;
    }

    /**
     * @deprecated Use {@link #get(boolean, boolean, boolean)}
     */
    @Deprecated
    public static LockGrade get(boolean read, boolean write)
    {
      return get((read ? 1 : 0) | (write ? 2 : 0));
    }

    /**
     * @since 4.1
     */
    public static LockGrade get(boolean read, boolean write, boolean option)
    {
      return get((read ? 1 : 0) | (write ? 2 : 0) | (option ? 4 : 0));
    }

    public static LockGrade get(int value)
    {
      switch (value)
      {
      case 0:
        return NONE;

      case 1:
        return READ;

      case 2:
        return WRITE;

      case 3:
        return READ_WRITE;

      case 4:
        return OPTION;

      case 1 | 4:
        return READ_OPTION;

      case 2 | 4:
        return WRITE_OPTION;

      case 1 | 2 | 4:
        return READ_WRITE_OPTION;

      default:
        throw new IllegalArgumentException("Invalid lock grade: " + value);
      }
    }
  }
}
