/*
 * This file is part of the Vamsas Client version 0.2. 
 * Copyright 2010 by Jim Procter, Iain Milne, Pierre Marguerite, 
 *  Andrew Waterhouse and Dominik Lindner.
 * 
 * Earlier versions have also been incorporated into Jalview version 2.4 
 * since 2008, and TOPALi version 2 since 2007.
 * 
 * The Vamsas Client is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *  
 * The Vamsas Client is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with the Vamsas Client.  If not, see <http://www.gnu.org/licenses/>.
 */
package uk.ac.vamsas.client.simpleclient;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.nio.channels.ByteChannel;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;

import org.apache.commons.logging.LogFactory;

/**
 * transient object representing a file lock This lock should hold for all
 * processes interacting in a session.
 * 
 * @author jimp
 */

public abstract class Lock {
  protected org.apache.commons.logging.Log log = LogFactory.getLog(Lock.class);

  File target = null; // The file that is being locked

  protected RandomAccessFile rafile = null;

  /**
   * creates a valid Lock (test with <method>isLocked</method>) if a lock could
   * be obtained for <param>lockfile</param>
   * 
   * @param lockfile
   */
  protected Lock(java.io.File lockfile) {
    target = lockfile;
  }

  /**
   * test whether the given file is a target or related to the lock on the
   * target file.
   * 
   * @param afile
   *          a file
   * @return true if target is locked and afile is related to target
   */
  public abstract boolean isTargetLockFile(File afile);

  /**
   * 
   * @return true if lock is held on the target
   */
  public abstract boolean isLocked();

  /**
   * release lock and close all managed channels to file
   * 
   */
  public abstract void release();

  /**
   * optionally close the open random access channel on the file when releasing
   * lock
   * 
   * @param closeChannel
   */
  public abstract void release(boolean closeChannel);

  /**
   * gets Locked Stream for reading from
   * 
   * @param atStart
   *          true to start reading at beginning of file.
   * @return null if file not locked
   * @throws IOException
   */
  public abstract FileInputStream getFileInputStream(boolean atStart)
      throws IOException;

  /**
   * gets Locked stream to write to FileInput always starts at the *end* of the
   * file (after any truncation)
   * 
   * @param clear
   *          true means file will be cleared to zero length
   * @return null if file is not locked
   * @throws IOException
   */
  public abstract FileOutputStream getFileOutputStream(boolean clear)
      throws IOException;

  /**
   * return buffered output stream to locked file.
   * 
   * @param clear
   *          - true means file is truncated to 0 length before writing
   * @return
   */
  public abstract BufferedOutputStream getBufferedOutputStream(boolean clear)
      throws IOException;

  protected void finalize() throws Throwable {
    target = null;
  }

  /**
   * return buffered input stream for locked file.
   * 
   * @param atStart
   *          - true means read from begining of file
   * @return null if file is not locked.
   */
  public BufferedInputStream getBufferedInputStream(boolean atStart)
      throws IOException {
    FileInputStream fis = getFileInputStream(atStart);
    if (fis != null)
      return new BufferedInputStream(fis);
    return null;
  }

  /**
   * safe lock target length() function.
   * 
   * @return -1 for non-lockable target, otherwise target's file length
   */
  public abstract long length();

  public abstract RandomAccessFile getRaFile() throws IOException;

  public abstract FileChannel getRaChannel() throws IOException;
}
