/*
 * CorbaHist1DAdapter.java
 *
 * Created on June 12, 2003, 5:54 PM
 */

package hep.aida.ref.remote.testRemote.converters;

//import hep.aida.dev.IConverter;
import hep.aida.IAnnotation;
import hep.aida.IAxis;
import hep.aida.IHistogram1D;
import hep.aida.IManagedObject;
import hep.aida.ref.Annotation;

import hep.aida.ref.histogram.Histogram1D;
import hep.aida.ref.remote.RemoteHistogram1D;

/**
 * Converts Hist1DData to RemoteHistogram1D
 * @author  serbo
 */
public final class TestHist1DConverter extends TestConverter {
    
    private static TestHist1DConverter converter = null;
    
    /** Creates a new instance of CorbaHist1DAdapter */
    public static TestHist1DConverter getInstance() {
        if (converter == null) converter = new TestHist1DConverter();
        return converter;
    }
    
    private TestHist1DConverter() {
        super();
        dataType = "IHistogram1D";
        aidaType = "IHistogram1D";
    }
    
    
    /**
     * Creates new instance of type "type".
     */
    public Object createAidaObject(String name) {
        RemoteHistogram1D result = new RemoteHistogram1D(name);        
        return result;
    }
    
    /**
     * Updates data contained by object.
     * Input must be IHistogram1D.
     */
    public boolean updateAidaObject(Object aidaObject, Object newData) {
        IHistogram1D data = null;
        if (newData instanceof IHistogram1D) {
            data = (IHistogram1D) newData;
        }
        
        if (!(aidaObject instanceof hep.aida.ref.remote.RemoteHistogram1D))
            throw new IllegalArgumentException("Not supported object type: "+aidaObject.getClass().getName());
        if (!(data instanceof IHistogram1D))
            throw new IllegalArgumentException("Not supported data type: "+(data == null ? "null" : newData.getClass().getName()));

        updateData((RemoteHistogram1D) aidaObject, data);
        return true;
    }
  
    /**
     * Returns IHistogram1D object
     */
    public Object extractData(Object aidaObject) {
        if (!(aidaObject instanceof hep.aida.IHistogram1D))
            throw new IllegalArgumentException("Not supported data type: "+aidaObject.getClass().getName());

        IHistogram1D data = null;
        synchronized (aidaObject) {
            data = createData((hep.aida.IHistogram1D) aidaObject);
        }
        
        return data;
    }
  
    
   /**
    * Update data in RemoteHistogram1d from IHistogram1D
    * and calls setDataValid(true) method.
    */ 
   public IManagedObject updateData(RemoteHistogram1D hist, IHistogram1D data)
   {
       hist.setFillable(true);
       
      // Check if X axis binning or edges are different
      IAxis lAxis = hist.axis();      
      IAxis rAxis = data.axis();  
      int nBins = rAxis.bins();
      IAxis newAxis = null;
      if (lAxis == null || lAxis.bins() != nBins || 
          lAxis.lowerEdge() != rAxis.lowerEdge() || lAxis.upperEdge() != rAxis.upperEdge()) {
          hist.setAxis(nBins, rAxis.lowerEdge(), rAxis.upperEdge()); 
      }
      
      // Check and set Annotation
      if (data.annotation() != null && data.annotation().size() > 0) {
          boolean sticky = false;
          IAnnotation localAnnotation = hist.annotation();
          if (localAnnotation instanceof Annotation)  
              ((Annotation) localAnnotation).setFillable(true);
          for (int i=0; i<data.annotation().size(); i++) {
              String key = data.annotation().key(i);
              String newValue = data.annotation().value(key);
              String oldValue = null;
              try {
                  oldValue = localAnnotation.value(key);
              } catch (IllegalArgumentException e) {}
              if (oldValue == null) localAnnotation.addItem(key, newValue, sticky);
              else if (!newValue.equals(oldValue)) {
                  localAnnotation.setValue(key,  newValue);
                  localAnnotation.setSticky(key,  sticky);
              }
          }
          if (localAnnotation instanceof Annotation)  
              ((Annotation) localAnnotation).setFillable(false);          
      }
      
      // Set bin information
      int[] entries    = null;
      double[] heights = null;
      double[] errors  = null;
      double[] means   = null;
      double[] rmss    = null;
      if (nBins > 0) {
        entries    = new int[nBins+2];
        heights = new double[nBins+2];
        errors  = new double[nBins+2];
        means   = new double[nBins+2];
        rmss    = new double[nBins+2];
        int i = 0;
        for (i=0; i<nBins; i++) {
            heights[i+1] = data.binHeight(i);
            errors[i+1]  = data.binError(i);
            entries[i+1] = data.binEntries(i);
            means[i+1]   = data.binMean(i);
            if (data instanceof Histogram1D) rmss[i+1]    = ((Histogram1D) data).binRms(i);
        }
        
        // UNDERFLOW_BIN
        i = IAxis.UNDERFLOW_BIN;
        int j = 0;
        heights[j] = data.binHeight(i);
        errors[j]  = data.binError(i);
        entries[j] = data.binEntries(i);
        means[j]   = data.binMean(i);
        if (data instanceof Histogram1D) rmss[j]    = ((Histogram1D) data).binRms(i);
      
        // OVERFLOW_BIN
        i = IAxis.OVERFLOW_BIN;
        j = nBins+1;
        heights[j] = data.binHeight(i);
        errors[j]  = data.binError(i);
        entries[j] = data.binEntries(i);
        means[j]   = data.binMean(i);
        if (data instanceof Histogram1D) rmss[j]    = ((Histogram1D) data).binRms(i);
      }
      synchronized (hist) {
        hist.setHeights(heights);
        hist.setErrors(errors);
        hist.setEntries(entries);
        hist.setMeans(means);
        hist.setRmss(rmss);
        hist.setMean(data.mean());
        hist.setRms(data.rms());

        hist.setFillable(false);
        hist.setDataValid(true);
      }
      return hist;
   }
   
   /**
    * Create Hist1DData structure from an IHistogram1D
    */
    public IHistogram1D createData(IHistogram1D hist) {
        IHistogram1D data = hist;

        return data;
    } 
    
}