package neurospy.protocol.autooffset;
 
import digitizer.Digitizer;
import digitizer.Digitizers;
import java.io.IOException;
import org.openide.filesystems.FileObject;
import org.openide.loaders.DataObjectNotFoundException;
 
/**
 * Adjusts digitizer offset during acquisition to keep perceived image
 * brightness within the given limits.
 *
 * @author Dejan Vu&#x010Dini&#x0107 <dejan@salk.edu>
 */
public class AutoOffsetAdjuster implements scheduler.Schedulable {
 
    public static final String ATTRIBUTE_NAME = "dataflowname";
    public static final String ATTRIBUTE_CHANNEL = "channel";
    public static final String ATTRIBUTE_INTERVAL = "checkeveryms";
    public static final String ATTRIBUTE_TARGET = "target";
    public static final String ATTRIBUTE_SLOP = "slop";
    public static final String ATTRIBUTE_SPEED = "speed";
    public static final String ATTRIBUTE_OFFSET = "offset";
 
    /** Creates a new instance of AutoOffsetAdjuster */
    public static AutoOffsetAdjuster create(final FileObject fo) throws DataObjectNotFoundException, IOException, ClassNotFoundException {
        AutoOffsetAdjuster instance = new AutoOffsetAdjuster(fo);
        return instance;
    }
 
    private FileObject m_fo;
    private double m_offset; // gets written out as an attribute
 
    private String m_name;
    private int m_channel, m_interval;
    private double m_target, m_slop, m_speed;
    private Digitizer m_digitizer;
 
    private AutoOffsetAdjuster(FileObject fo) {
        m_fo = fo;
        m_name = (String) fo.getAttribute(ATTRIBUTE_NAME);
        m_channel = (Integer) fo.getAttribute(ATTRIBUTE_CHANNEL);
        m_interval = (Integer) fo.getAttribute(ATTRIBUTE_INTERVAL);
        m_target = (Double) fo.getAttribute(ATTRIBUTE_TARGET);
        m_slop = (Double) fo.getAttribute(ATTRIBUTE_SLOP);
        m_speed = (Double) fo.getAttribute(ATTRIBUTE_SPEED);
        try {
            m_offset = (Double) fo.getAttribute(ATTRIBUTE_OFFSET);
        } catch (Exception e) {
            // first time
            m_offset = 0;
            try {
                m_fo.setAttribute(ATTRIBUTE_OFFSET, new Double(m_offset));
            } catch (IOException ex) {
                throw new IllegalStateException(ex);
            }
        }
    }
 
 
    public void configure() { }
 
    private Sniffer m_sniffer;
 
    public void initialize() {
        m_digitizer = Digitizers.getDefault();
        m_sniffer = (Sniffer) dataflow.DataFlow.find(m_name).findComponent("imageinput");
    }
 
    public void prepare() {
        m_digitizer.setVerticalOffset(m_channel, m_offset);
    }
 
    public void arm() { }
 
    private long m_lastchecked;
 
    public void run() {
        if (System.currentTimeMillis() > m_lastchecked + m_interval) {
            double est = m_sniffer.sniff();
            if (est > m_target + m_slop || est < m_target - m_slop) {
                double offset = m_digitizer.getVerticalOffset(m_channel);
                m_offset = offset - m_digitizer.getVerticalRange(m_channel) * (est - m_target) * m_speed;
                m_digitizer.setVerticalOffset(m_channel, m_offset);
                try {
                    m_fo.setAttribute(ATTRIBUTE_OFFSET, new Double(m_offset));
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            } else {
                m_lastchecked = System.currentTimeMillis();
            }
        }
    }
 
    public void cleanup() { }
 
    public void interrupted() { }
 
}