package de.renew.formalism.fs;

import de.uni_hamburg.fs.FeatureStructure;
import de.uni_hamburg.fs.JavaObject;
import de.uni_hamburg.fs.NoSuchFeatureException;
import de.uni_hamburg.fs.Path;

import de.renew.expression.Function;
import de.renew.unify.Impossible;


/**
 * FSAtFunction represents the “@” operator for feature structures —
 * it extracts the value of a given feature (or nested feature path) from a structure.
 */
public class FSAtFunction implements Function {

    /**
     * The extraction path.
     */
    Path _path;
    /**
     * Whether the retrieved value should be unpacked.
     */
    boolean _unpacking = true;

    /**
     * Creates an instance of FSATFunction with an extraction path from a string.
     * @param feat the string representation of the path
     */
    public FSAtFunction(String feat) {
        _path = new Path(feat);
    }

    /**
     * Creates an instance of FSAtFunction with a path object for the extraction location
     * and a boolean if the value should be unpacked
     * @param path the extraction path
     * @param unpacking Whether the retrieved value should be unpacked.
     */
    public FSAtFunction(Path path, boolean unpacking) {
        this._path = path;
        this._unpacking = unpacking;
    }

    @Override
    public Object function(Object param) throws Impossible {
        FeatureStructure fs;
        if (param instanceof FeatureStructure) {
            fs = (FeatureStructure) param;
        } else {
            fs = new FeatureStructure(JavaObject.getJavaType(param));
        }
        try {
            if (_unpacking) {
                return fs.unpackingAt(_path);
            } else {
                return fs.at(_path);
            }
        } catch (NoSuchFeatureException nsf) {
            throw new Impossible(nsf.getMessage());
        }
    }
}