package com.srbenoit.filter;

import java.awt.image.BufferedImage;
import com.srbenoit.filter.items.ByteArrayPipeItem;
import com.srbenoit.filter.items.ImageArrayPipeItem;
import com.srbenoit.filter.items.PointSetArrayPipeItem;
import com.srbenoit.filter.items.StringPipeItem;
import com.srbenoit.filter.items.TimeSeriesPipeItem;
import com.srbenoit.filter.items.TrajectoryListPipeItem;
import com.srbenoit.util.ResourceLoader;

/**
 * A specification for an input required by a filter.
 */
public class FilterInput {

    /** the data type of the input */
    public final Class<? extends AbstractPipeItem> type;

    /** a description of the input */
    public final String description;

    /** the key of the pipe item the filter will actually take its input from */
    private String actualKey;

    /** the icon that represents the output */
    private final BufferedImage icon;

    /**
     * Constructs a new <code>FilterInput</code>.
     *
     * @param  clazz  the data type of the input
     * @param  desc   a description of the input
     */
    public FilterInput(final Class<? extends AbstractPipeItem> clazz, final String desc) {

        BufferedImage img;

        if (clazz == null) {
            throw new IllegalArgumentException("input data type cannot be null");
        }

        if (desc == null) {
            throw new IllegalArgumentException("input data description cannot be null");
        }

        this.type = clazz;
        this.description = desc;

        this.actualKey = null;

        if (clazz.equals(ByteArrayPipeItem.class)) {
            img = ResourceLoader.loadImage(FilterOutput.class, "icons/binary.png");
        } else if (clazz.equals(ImageArrayPipeItem.class)) {
            img = ResourceLoader.loadImage(FilterOutput.class, "icons/images.png");
        } else if (clazz.equals(PointSetArrayPipeItem.class)) {
            img = ResourceLoader.loadImage(FilterOutput.class, "icons/point_set.png");
        } else if (clazz.equals(StringPipeItem.class)) {
            img = ResourceLoader.loadImage(FilterOutput.class, "icons/text.png");
        } else if (clazz.equals(TimeSeriesPipeItem.class)) {
            img = ResourceLoader.loadImage(FilterOutput.class, "icons/time_series.png");
        } else if (clazz.equals(TrajectoryListPipeItem.class)) {
            img = ResourceLoader.loadImage(FilterOutput.class, "icons/trajectories.png");
        } else {
            img = null;
        }

        if (img == null) {
            this.icon = new BufferedImage(24, 16, BufferedImage.TYPE_INT_RGB);
        } else {
            this.icon = img;
        }
    }

    /**
     * Sets the key of the pipe item from which the input will be taken.
     *
     * @param  key  the key
     */
    public void setKey(final String key) {

        this.actualKey = key;
    }

    /**
     * Gets the key of the pipe item from which the input will be taken.
     *
     * @return  the key
     */
    public String getKey() {

        return this.actualKey;
    }

    /**
     * Tests whether another object is equal to this <code>FilterInput</code>. In order to be
     * considered equal, the object must be a <code>FilterInput</code> and must have the same
     * values for all fields.
     *
     * @param   obj  the object to test
     * @return  <code>true</code> if the object is equal to this <code>FilterInput</code>; <code>
     *          false</code> otherwise
     */
    @Override public boolean equals(final Object obj) {

        FilterInput other;
        boolean equal;

        if (obj instanceof FilterInput) {
            other = (FilterInput) obj;
            equal = other.type.equals(this.type) && other.description.equals(this.description)
                && ((this.actualKey == null) ? (other.getKey() == null)
                                             : this.actualKey.equals(other.getKey()));
        } else {
            equal = false;
        }

        return equal;
    }

    /*
     * Gets the hash code for the object.
     *
     * @return the hash code
     */
    @Override public int hashCode() {

        return this.type.hashCode() + description.hashCode()
            + ((this.actualKey == null) ? 0 : this.actualKey.hashCode());
    }

    /**
     * Gets a 24x16 icon representing the filter input data type
     *
     * @return  the icon
     */
    public BufferedImage getIcon() {

        return this.icon;
    }
}
