/*
 * Copyright (c) 2008-2012, 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:
 *    Simon McDuff - initial API and implementation
 *    Eike Stepper - maintenance
 */
package org.eclipse.net4j.util.concurrent;

import org.eclipse.net4j.util.ObjectUtil;
import org.eclipse.net4j.util.collection.HashBag;
import org.eclipse.net4j.util.lifecycle.Lifecycle;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * Support Multiple reads/no write and upgrade lock from read to write. Many context could request
 * {@link IRWLockManager.LockType#WRITE write} lock at the same time. It will privileges first context that has already
 * a {@link IRWLockManager.LockType#READ read} lock. If no one has any read lock, it's "first come first serve".
 *
 * @author Simon McDuff
 * @since 2.0
 * @deprecated Use {@link RWOLockManager}
 */
@Deprecated
public class RWLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWLockManager<OBJECT, CONTEXT>
{
  private LockStrategy<OBJECT, CONTEXT> readLockStrategy = new LockStrategy<OBJECT, CONTEXT>()
  {
    public boolean isLocked(LockEntry<OBJECT, CONTEXT> entry, CONTEXT context)
    {
      return entry.isReadLock(context);
    }

    public boolean isLockedByOthers(LockEntry<OBJECT, CONTEXT> entry, CONTEXT context)
    {
      return entry.isReadLockByOthers(context);
    }

    public boolean canObtainLock(LockEntry<OBJECT, CONTEXT> entry, CONTEXT context)
    {
      return entry.canObtainReadLock(context);
    }

    public LockEntry<OBJECT, CONTEXT> lock(LockEntry<OBJECT, CONTEXT> entry, CONTEXT context)
    {
      return entry.readLock(context);
    }

    public LockEntry<OBJECT, CONTEXT> unlock(LockEntry<OBJECT, CONTEXT> entry, CONTEXT context)
    {
      return entry.readUnlock(context);
    }

    @Override
    public String toString()
    {
      return "ReadLockStrategy";
    }
  };

  private LockStrategy<OBJECT, CONTEXT> writeLockStrategy = new LockStrategy<OBJECT, CONTEXT>()
  {
    public boolean isLocked(LockEntry<OBJECT, CONTEXT> entry, CONTEXT context)
    {
      return entry.isWriteLock(context);
    }

    public boolean isLockedByOthers(LockEntry<OBJECT, CONTEXT> entry, CONTEXT context)
    {
      return entry.isWriteLockByOthers(context);
    }

    public boolean canObtainLock(LockEntry<OBJECT, CONTEXT> entry, CONTEXT context)
    {
      return entry.canObtainWriteLock(context);
    }

    public LockEntry<OBJECT, CONTEXT> lock(LockEntry<OBJECT, CONTEXT> entry, CONTEXT context)
    {
      return entry.writeLock(context);
    }

    public LockEntry<OBJECT, CONTEXT> unlock(LockEntry<OBJECT, CONTEXT> entry, CONTEXT context)
    {
      return entry.writeUnlock(context);
    }

    @Override
    public String toString()
    {
      return "WriteLockStrategy";
    }
  };

  private Map<OBJECT, LockEntry<OBJECT, CONTEXT>> lockEntries = new HashMap<OBJECT, LockEntry<OBJECT, CONTEXT>>();

  private LockChanged lockChanged = new LockChanged();

  /**
   * @since 3.0
   */
  public void lock(LockType type, CONTEXT context, Collection<? extends OBJECT> objectsToLock, long timeout)
      throws InterruptedException
  {
    LockStrategy<OBJECT, CONTEXT> lockingStrategy = getLockingStrategy(type);
    lock(lockingStrategy, context, objectsToLock, timeout);
  }

  /**
   * @since 3.0
   */
  public void lock(LockType type, CONTEXT context, OBJECT objectToLock, long timeout) throws InterruptedException
  {
    List<OBJECT> objectsToLock = Collections.singletonList(objectToLock);
    lock(type, context, objectsToLock, timeout);
  }

  /**
   * Attempts to release for a given locktype, context and objects.
   *
   * @throws IllegalMonitorStateException
   *           Unlocking objects without lock.
   * @since 3.0
   */
  public void unlock(LockType type, CONTEXT context, Collection<? extends OBJECT> objectsToUnlock)
  {
    LockStrategy<OBJECT, CONTEXT> lockingStrategy = getLockingStrategy(type);
    unlock(lockingStrategy, context, objectsToUnlock);
  }

  /**
   * Attempts to release all locks(read and write) for a given context.
   */
  public void unlock(CONTEXT context)
  {
    synchronized (lockChanged)
    {
      List<LockEntry<OBJECT, CONTEXT>> lockEntrysToRemove = new ArrayList<LockEntry<OBJECT, CONTEXT>>();
      List<LockEntry<OBJECT, CONTEXT>> lockEntrysToAdd = new ArrayList<LockEntry<OBJECT, CONTEXT>>();

      for (Entry<OBJECT, LockEntry<OBJECT, CONTEXT>> entry : lockEntries.entrySet())
      {
        LockEntry<OBJECT, CONTEXT> lockedContext = entry.getValue();
        LockEntry<OBJECT, CONTEXT> newEntry = lockedContext.clearLock(context);
        if (newEntry == null)
        {
          lockEntrysToRemove.add(lockedContext);
        }
        else if (newEntry != entry)
        {
          lockEntrysToAdd.add(newEntry);
        }
      }

      for (LockEntry<OBJECT, CONTEXT> lockEntry : lockEntrysToRemove)
      {
        OBJECT object = lockEntry.getObject();
        lockEntries.remove(object);
      }

      for (LockEntry<OBJECT, CONTEXT> lockEntry : lockEntrysToAdd)
      {
        OBJECT object = lockEntry.getObject();
        lockEntries.put(object, lockEntry);
      }

      lockChanged.notifyAll();
    }
  }

  /**
   * @since 3.0
   */
  public boolean hasLock(LockType type, CONTEXT context, OBJECT objectToLock)
  {
    LockStrategy<OBJECT, CONTEXT> lockingStrategy = getLockingStrategy(type);
    return hasLock(lockingStrategy, context, objectToLock);
  }

  /**
   * @since 3.0
   */
  public boolean hasLockByOthers(LockType type, CONTEXT context, OBJECT objectToLock)
  {
    LockStrategy<OBJECT, CONTEXT> lockingStrategy = getLockingStrategy(type);
    LockEntry<OBJECT, CONTEXT> entry = getLockEntry(objectToLock);
    return entry != null && lockingStrategy.isLockedByOthers(entry, context);
  }

  /**
   * @since 3.1
   */
  protected void handleLockEntries(CONTEXT context, LockEntryHandler<OBJECT, CONTEXT> handler)
  {
    synchronized (lockChanged)
    {
      for (LockEntry<OBJECT, CONTEXT> lockEntry : lockEntries.values())
      {
        if (context == null || lockEntry.hasContext(context))
        {
          if (!handler.handleLockEntry(lockEntry))
          {
            break;
          }
        }
      }
    }
  }

  /**
   * @since 3.1
   */
  protected LockEntry<OBJECT, CONTEXT> getLockEntry(OBJECT objectToLock)
  {
    synchronized (lockChanged)
    {
      return lockEntries.get(objectToLock);
    }
  }

  /**
   * @since 3.1
   */
  protected LockStrategy<OBJECT, CONTEXT> getLockingStrategy(LockType type)
  {
    if (type == LockType.READ)
    {
      return readLockStrategy;
    }

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

    throw new IllegalArgumentException("Invalid lock type: " + type);
  }

  /**
   * @since 3.1
   */
  protected void changeContext(CONTEXT oldContext, CONTEXT newContext)
  {
    synchronized (lockChanged)
    {
      for (LockEntry<OBJECT, CONTEXT> lockEntry : lockEntries.values())
      {
        lockEntry.changeContext(oldContext, newContext);
      }
    }
  }

  /**
   * Attempts to release this lock.
   * <p>
   * If the number of context is now zero then the lock is made available for write lock attempts.
   *
   * @throws IllegalMonitorStateException
   *           Unlocking object not locked.
   */
  private void unlock(LockStrategy<OBJECT, CONTEXT> lockingStrategy, CONTEXT context,
      Collection<? extends OBJECT> objectsToLock)
  {
    synchronized (lockChanged)
    {
      List<LockEntry<OBJECT, CONTEXT>> lockEntrysToRemove = new ArrayList<LockEntry<OBJECT, CONTEXT>>();
      List<LockEntry<OBJECT, CONTEXT>> lockEntrysToAdd = new ArrayList<LockEntry<OBJECT, CONTEXT>>();
      for (OBJECT objectToLock : objectsToLock)
      {
        LockEntry<OBJECT, CONTEXT> entry = lockEntries.get(objectToLock);
        if (entry == null)
        {
          throw new IllegalMonitorStateException();
        }

        LockEntry<OBJECT, CONTEXT> newEntry = lockingStrategy.unlock(entry, context);
        if (newEntry == null)
        {
          lockEntrysToRemove.add(entry);
        }
        else if (newEntry != entry)
        {
          lockEntrysToAdd.add(newEntry);
        }
      }

      for (LockEntry<OBJECT, CONTEXT> lockEntry : lockEntrysToRemove)
      {
        OBJECT object = lockEntry.getObject();
        lockEntries.remove(object);
      }

      for (LockEntry<OBJECT, CONTEXT> lockEntry : lockEntrysToAdd)
      {
        OBJECT object = lockEntry.getObject();
        lockEntries.put(object, lockEntry);
      }

      lockChanged.notifyAll();
    }
  }

  private boolean hasLock(LockStrategy<OBJECT, CONTEXT> lockingStrategy, CONTEXT context, OBJECT objectToLock)
  {
    LockEntry<OBJECT, CONTEXT> entry = getLockEntry(objectToLock);
    return entry != null && lockingStrategy.isLocked(entry, context);
  }

  private void lock(LockStrategy<OBJECT, CONTEXT> lockStrategy, CONTEXT context,
      Collection<? extends OBJECT> objectsToLocks, long timeout) throws InterruptedException
  {
    long startTime = System.currentTimeMillis();
    while (true)
    {
      synchronized (lockChanged)
      {
        OBJECT conflict = obtainLock(lockStrategy, context, objectsToLocks);
        if (conflict == null)
        {
          lockChanged.notifyAll();
          return;
        }

        long elapsedTime = System.currentTimeMillis() - startTime;
        if (timeout != WAIT && elapsedTime > timeout)
        {
          throw new TimeoutRuntimeException("Could not lock " + conflict + " within " + timeout + " milli seconds"); //$NON-NLS-1$
        }

        if (timeout == WAIT)
        {
          lockChanged.wait();
        }
        else
        {
          lockChanged.wait(Math.max(1, timeout - elapsedTime));
        }
      }
    }
  }

  private OBJECT obtainLock(LockStrategy<OBJECT, CONTEXT> lockingStrategy, CONTEXT context,
      Collection<? extends OBJECT> objectsToLock)
  {
    List<LockEntry<OBJECT, CONTEXT>> lockEntrys = new ArrayList<LockEntry<OBJECT, CONTEXT>>();
    for (OBJECT objectToLock : objectsToLock)
    {
      LockEntry<OBJECT, CONTEXT> entry = lockEntries.get(objectToLock);
      if (entry == null)
      {
        entry = new NoLockEntry<OBJECT, CONTEXT>(objectToLock);
      }

      if (lockingStrategy.canObtainLock(entry, context))
      {
        lockEntrys.add(entry);
      }
      else
      {
        return objectToLock;
      }
    }

    for (LockEntry<OBJECT, CONTEXT> lockEntry : lockEntrys)
    {
      OBJECT object = lockEntry.getObject();
      LockEntry<OBJECT, CONTEXT> lock = lockingStrategy.lock(lockEntry, context);
      lockEntries.put(object, lock);
    }

    return null;
  }

  /**
   * @author Simon McDuff
   * @since 3.1
   * @deprecated Use {@link RWOLockManager}
   */
  @Deprecated
  protected interface LockStrategy<OBJECT, CONTEXT>
  {
    public boolean isLocked(LockEntry<OBJECT, CONTEXT> entry, CONTEXT context);

    public boolean isLockedByOthers(LockEntry<OBJECT, CONTEXT> entry, CONTEXT context);

    public boolean canObtainLock(LockEntry<OBJECT, CONTEXT> entry, CONTEXT context);

    public LockEntry<OBJECT, CONTEXT> lock(LockEntry<OBJECT, CONTEXT> entry, CONTEXT context);

    public LockEntry<OBJECT, CONTEXT> unlock(LockEntry<OBJECT, CONTEXT> entry, CONTEXT context);
  }

  /**
   * @author Simon McDuff
   * @since 3.1
   * @deprecated Use {@link RWOLockManager}
   */
  @Deprecated
  protected interface LockEntry<OBJECT, CONTEXT>
  {
    public OBJECT getObject();

    public boolean isReadLock(CONTEXT context);

    public boolean isWriteLock(CONTEXT context);

    public boolean isReadLockByOthers(CONTEXT context);

    public boolean isWriteLockByOthers(CONTEXT context);

    public boolean canObtainReadLock(CONTEXT context);

    public boolean canObtainWriteLock(CONTEXT context);

    public LockEntry<OBJECT, CONTEXT> readLock(CONTEXT context);

    public LockEntry<OBJECT, CONTEXT> writeLock(CONTEXT context);

    public LockEntry<OBJECT, CONTEXT> readUnlock(CONTEXT context);

    public LockEntry<OBJECT, CONTEXT> writeUnlock(CONTEXT context);

    public LockEntry<OBJECT, CONTEXT> clearLock(CONTEXT context);

    /**
     * @since 3.1
     */
    public void changeContext(CONTEXT oldContext, CONTEXT newContext);

    /**
     * @since 3.1
     */
    public boolean hasContext(CONTEXT context);
  }

  /**
   * @author Eike Stepper
   * @since 3.1
   * @deprecated Use {@link RWOLockManager}
   */
  @Deprecated
  protected interface LockEntryHandler<OBJECT, CONTEXT>
  {
    public boolean handleLockEntry(LockEntry<OBJECT, CONTEXT> lockEntry);
  }

  /**
   * @author Simon McDuff
   */
  private static final class ReadLockEntry<OBJECT, CONTEXT> implements LockEntry<OBJECT, CONTEXT>
  {
    private OBJECT object;

    private Set<CONTEXT> contexts = new HashBag<CONTEXT>();

    public ReadLockEntry(OBJECT objectToLock, CONTEXT context)
    {
      this.object = objectToLock;
      contexts.add(context);
    }

    public OBJECT getObject()
    {
      return object;
    }

    public boolean isReadLock(CONTEXT context)
    {
      return contexts.contains(context);
    }

    public boolean isWriteLock(CONTEXT context)
    {
      return false;
    }

    public boolean isReadLockByOthers(CONTEXT context)
    {
      if (contexts.isEmpty())
      {
        return false;
      }

      return contexts.size() > (isReadLock(context) ? 1 : 0);
    }

    public boolean isWriteLockByOthers(CONTEXT context)
    {
      return false;
    }

    public boolean canObtainReadLock(CONTEXT context)
    {
      return true;
    }

    public boolean canObtainWriteLock(CONTEXT context)
    {
      return contexts.size() == 1 && contexts.contains(context);
    }

    public LockEntry<OBJECT, CONTEXT> readLock(CONTEXT context)
    {
      contexts.add(context);
      return this;
    }

    public LockEntry<OBJECT, CONTEXT> writeLock(CONTEXT context)
    {
      return new WriteLockEntry<OBJECT, CONTEXT>(object, context, this);
    }

    public LockEntry<OBJECT, CONTEXT> readUnlock(CONTEXT context)
    {
      contexts.remove(context);
      return contexts.isEmpty() ? null : this;
    }

    public LockEntry<OBJECT, CONTEXT> writeUnlock(CONTEXT context)
    {
      throw new IllegalMonitorStateException();
    }

    public LockEntry<OBJECT, CONTEXT> clearLock(CONTEXT context)
    {
      while (contexts.remove(context))
      {
      }

      return contexts.isEmpty() ? null : this;
    }

    public void changeContext(CONTEXT oldContext, CONTEXT newContext)
    {
      if (contexts.remove(oldContext))
      {
        contexts.add(newContext);
      }
    }

    public boolean hasContext(CONTEXT context)
    {
      return contexts.contains(context);
    }

    @Override
    public String toString()
    {
      return MessageFormat.format("ReadLockEntry[object={0}, contexts={1}]", object, contexts);
    }
  }

  /**
   * @author Simon McDuff
   */
  private static final class WriteLockEntry<OBJECT, CONTEXT> implements LockEntry<OBJECT, CONTEXT>
  {
    private OBJECT object;

    private CONTEXT context;

    private int count;

    private ReadLockEntry<OBJECT, CONTEXT> readLock;

    public WriteLockEntry(OBJECT object, CONTEXT context, ReadLockEntry<OBJECT, CONTEXT> readLock)
    {
      this.object = object;
      this.context = context;
      this.readLock = readLock;
      this.count = 1;
    }

    public OBJECT getObject()
    {
      return object;
    }

    public boolean isReadLock(CONTEXT context)
    {
      return readLock != null ? readLock.isReadLock(context) : false;
    }

    public boolean isWriteLock(CONTEXT context)
    {
      return ObjectUtil.equals(this.context, context);
    }

    public boolean isReadLockByOthers(CONTEXT context)
    {
      return readLock != null ? readLock.isReadLockByOthers(context) : false;
    }

    public boolean isWriteLockByOthers(CONTEXT context)
    {
      return context != this.context;
    }

    public boolean canObtainWriteLock(CONTEXT context)
    {
      return ObjectUtil.equals(this.context, context);
    }

    public boolean canObtainReadLock(CONTEXT context)
    {
      return ObjectUtil.equals(this.context, context);
    }

    public LockEntry<OBJECT, CONTEXT> readLock(CONTEXT context)
    {
      ReadLockEntry<OBJECT, CONTEXT> lock = getReadLock();
      lock.readLock(context);
      return this;
    }

    public LockEntry<OBJECT, CONTEXT> writeLock(CONTEXT context)
    {
      count++;
      return this;
    }

    public LockEntry<OBJECT, CONTEXT> readUnlock(CONTEXT context)
    {
      if (readLock != null)
      {
        if (readLock.readUnlock(context) == null)
        {
          readLock = null;
        }

        return this;
      }

      throw new IllegalMonitorStateException();
    }

    public LockEntry<OBJECT, CONTEXT> writeUnlock(CONTEXT context)
    {
      return --count <= 0 ? readLock : this;
    }

    public LockEntry<OBJECT, CONTEXT> clearLock(CONTEXT context)
    {
      if (readLock != null)
      {
        if (readLock.clearLock(context) == null)
        {
          readLock = null;
        }
      }

      return ObjectUtil.equals(this.context, context) ? readLock : this;
    }

    public void changeContext(CONTEXT oldContext, CONTEXT newContext)
    {
      if (ObjectUtil.equals(context, oldContext))
      {
        context = newContext;
      }
    }

    public boolean hasContext(CONTEXT context)
    {
      return ObjectUtil.equals(this.context, context);
    }

    @Override
    public String toString()
    {
      return MessageFormat.format("WriteLockEntry[object={0}, context={1}, count={2}]", object, context, count);
    }

    private ReadLockEntry<OBJECT, CONTEXT> getReadLock()
    {
      if (readLock == null)
      {
        readLock = new ReadLockEntry<OBJECT, CONTEXT>(object, context);
      }

      return readLock;
    }
  }

  /**
   * @author Simon McDuff
   */
  private static final class NoLockEntry<OBJECT, CONTEXT> implements LockEntry<OBJECT, CONTEXT>
  {
    private OBJECT object;

    public NoLockEntry(OBJECT objectToLock)
    {
      this.object = objectToLock;
    }

    public OBJECT getObject()
    {
      return object;
    }

    public boolean isReadLock(CONTEXT context)
    {
      throw new UnsupportedOperationException();
    }

    public boolean isWriteLock(CONTEXT context)
    {
      throw new UnsupportedOperationException();
    }

    public boolean isReadLockByOthers(CONTEXT context)
    {
      throw new UnsupportedOperationException();
    }

    public boolean isWriteLockByOthers(CONTEXT context)
    {
      throw new UnsupportedOperationException();
    }

    public boolean canObtainWriteLock(CONTEXT context)
    {
      return true;
    }

    public boolean canObtainReadLock(CONTEXT context)
    {
      return true;
    }

    public LockEntry<OBJECT, CONTEXT> readLock(CONTEXT context)
    {
      return new ReadLockEntry<OBJECT, CONTEXT>(object, context);
    }

    public LockEntry<OBJECT, CONTEXT> writeLock(CONTEXT context)
    {
      return new WriteLockEntry<OBJECT, CONTEXT>(object, context, null);
    }

    public LockEntry<OBJECT, CONTEXT> readUnlock(CONTEXT context)
    {
      throw new UnsupportedOperationException();
    }

    public LockEntry<OBJECT, CONTEXT> writeUnlock(CONTEXT context)
    {
      throw new UnsupportedOperationException();
    }

    public LockEntry<OBJECT, CONTEXT> clearLock(CONTEXT context)
    {
      throw new UnsupportedOperationException();
    }

    public void changeContext(CONTEXT oldContext, CONTEXT newContext)
    {
      // Do nothing
    }

    public boolean hasContext(CONTEXT context)
    {
      return false;
    }

    @Override
    public String toString()
    {
      return MessageFormat.format("NoLockEntry[object={0}]", object);
    }
  }

  /**
   * @author Eike Stepper
   */
  private static final class LockChanged
  {
  }
}
