package com.srbenoit.filter.items;

import java.io.File;
import java.util.logging.Level;
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 string.
 */
public class StringPipeItem extends AbstractPipeItem {

    /** the string data */
    private String data = null;

    /**
     * Constructs a new <code>StringPipeItem</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 StringPipeItem(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 String newData) {

        if (newData == null) {
            throw new IllegalArgumentException("Data may not be null");
        }

        this.data = newData;
        getFile(0).notPersisted();
    }

    /**
     * Gets this item's data.
     *
     * @return  the data
     */
    public String getData() {

        return this.data;
    }

    /**
     * Gets the name of this type.
     *
     * @return  the type name
     */
    @Override public String typeName() {

        return "String";
    }

    /**
     * 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);

        info = getFile(0);

        if (this.data == null) {
            result = false;
            info.notPersisted();
        } else {

            if (Pipe.writeFile(info.getFile(), this.data.getBytes())) {
                info.wasPersisted();
                result = true;
            } else {
                info.notPersisted();
                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;
        byte[] bytes;

        info = getFile(0);

        bytes = Pipe.readFile(info.getFile());

        if (bytes == null) {
            LOG.log(Level.INFO, "Unable to read string file: {0}",
                info.getFile().getAbsolutePath());
            this.data = null;
            info.notPersisted();
        } else {
            this.data = new String(bytes);
            info.wasPersisted();
        }

        return this.data != null;
    }

    /**
     * Creates a file that represents the object data.
     *
     * @param   dir  the directory where the item's files are stored
     * @return  the file
     */
    private File makeFile(final File dir) {

        return new File(dir, getKey() + "_String.txt");
    }
}
