package com.srbenoit.filter.items;

import java.io.File;
import com.srbenoit.filter.AbstractPipeItem;
import com.srbenoit.filter.FilterTreeExecutor;
import com.srbenoit.filter.Pipe;
import com.srbenoit.filter.PipeItemFileInfo;

/**
 * A simple pipe item that contains a non-null byte array.
 */
public class ByteArrayPipeItem extends AbstractPipeItem {

    /** the byte array data */
    private byte[] data = null;

    /**
     * Constructs a new <code>ByteArrayPipeItem</code>.
     *
     * @param  theKey    the unique key for the item
     * @param  theLabel  the label for the item (a human friendly name)
     * @param  thePipe   the pipe in which this item is installed
     */
    public ByteArrayPipeItem(final String theKey, final String theLabel, final Pipe thePipe) {

        super(theKey, theLabel, thePipe);

        PipeItemFileInfo info;

        info = new PipeItemFileInfo(makeFile(getSubdir()));
        addFile(info);
    }

    /**
     * Sets this item's data.
     *
     * @param  newData  the new data
     */
    public void setData(final byte[] newData) {

        if (newData == null) {
            throw new IllegalArgumentException("Data may not be null");
        }

        this.data = newData.clone();
        getFile(0).notPersisted();
    }

    /**
     * Gets this item's data.
     *
     * @return  the data
     */
    public byte[] getData() {

        return this.data.clone();
    }

    /**
     * Gets the name of this type.
     *
     * @return  the type name
     */
    @Override public String typeName() {

        return "byte[]";
    }

    /**
     * Resets the pipe item to a virgin (empty) state.
     */
    @Override public void reset() {

        this.data = null;
        getFile(0).notPersisted();
    }

    /**
     * Saves the item to a filesystem.
     *
     * @param   executor  the executor that is saving the pipe
     * @param   startPct  the starting progress percentage for the save operation
     * @param   endPct    the ending progress percentage for the save operation
     * @return  <code>true</code> on successful save; <code>false</code> on failure
     */
    @Override public boolean save(final FilterTreeExecutor executor, final int startPct,
        final int endPct) {

        PipeItemFileInfo info;
        boolean result;

        executor.indicateProgress((startPct + endPct) / 2);

        if (this.data == null) {
            LOG.warning("Byte array pipe item was marked dirty but had no data");
            result = true;
        } else {
            info = getFile(0);

            if (Pipe.writeFile(info.getFile(), this.data)) {
                info.wasPersisted();
                result = true;
            } else {
                result = false;
            }
        }

        return result;
    }

    /**
     * Loads the items from the filesystem.
     *
     * @return  <code>true</code> if the load succeeded; <code>false</code> if not
     */
    @Override public boolean load() {

        PipeItemFileInfo info;

        info = getFile(0);

        if (info.getFile().exists()) {
            this.data = Pipe.readFile(info.getFile());

            if (this.data == null) {
                info.notPersisted();
            } else {
                info.wasPersisted();
            }
        } else {
            info.notPersisted();
        }

        return this.data != null;
    }

    /**
     * Creates a file that represents the object data.
     *
     * @param   key   the key associated with the item
     * @param   pipe  the pipe in which this item is being loaded/saved
     * @return  the file
     */
    private File makeFile(final File dir) {

        return new File(dir, getKey() + "_ByteArray.dat");
    }
}
