/** 
 * 
 * Copyright 2004 Protique Ltd
 * 
 * Licensed 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.codehaus.activemq.message.util;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * Simply writes/reads data from a RandomAccessFile
 * 
 * @version $Revision: 1.1 $
 */
class FileDataBlock {
    private RandomAccessFile dataBlock;
    private File file;
    private long maxSize;
    private long currentOffset;

    /**
     * Constructor
     * 
     * @param file File handle
     * @param maxSize maximum size (in bytes) for the block
     * @throws IOException
     */
    FileDataBlock(File file, long maxSize) throws IOException {
        this.file = file;
        this.maxSize = maxSize;
        this.dataBlock = new RandomAccessFile(file, "rw");
        if (dataBlock.length() > 0) {
            this.currentOffset = dataBlock.readLong();//read header
        }
        else {
            dataBlock.writeLong(0);
            currentOffset = dataBlock.length();
        }
    }

    /**
     * close and deletes the block
     * 
     * @throws IOException
     */
    synchronized void close() throws IOException {
        dataBlock.close();
        file.delete();
    }

    /**
     * test to if there is enough room in the block to write the data
     * 
     * @param data bytes to be written
     * @return true if there is enough space left in the block to write the data
     * @throws IOException
     */
    synchronized boolean isEnoughSpace(byte[] data) throws IOException {
        return ((dataBlock.length() + data.length) < maxSize);
    }

    /**
     * Write data to the end of the block
     * 
     * @param data the bytes to write
     * @throws IOException
     */
    synchronized void write(byte[] data) throws IOException {
        dataBlock.seek(dataBlock.length());
        dataBlock.writeInt(data.length);
        dataBlock.write(data);
    }

    /**
     * read next chunk of data
     * 
     * @return next chunk of data or null if no more to read
     * @throws IOException
     */
    synchronized byte[] read() throws IOException {
        byte[] result = null;
        if (currentOffset > 0 && currentOffset < dataBlock.length()) {
            dataBlock.seek(currentOffset);
            int length = dataBlock.readInt();
            result = new byte[length];
            dataBlock.readFully(result);
            currentOffset = dataBlock.getFilePointer();
            updateHeader(currentOffset);
        }
        return result;
    }

    private void updateHeader(long pos) throws IOException {
        dataBlock.seek(0);
        dataBlock.writeLong(pos);
    }
}
