import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComFailException;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.DispatchEvents;
import com.jacob.com.Variant;


/**
 *
 * @author Claudiu Dinca - www.actualsoft.ro
 */

/*
 * 
 * help file : http://www.optimalprograms.com/help/optimization1dx/
 * component: http://www.optimalprograms.com/
 * 
 */
public class CutTest {
    private Dispatch cutController;
    private DispatchEvents events;
    
    public CutTest() {
		ComThread.InitMTA(true);
		ActiveXComponent cut1xCom = new ActiveXComponent("optimal1dx.Optimization1DX");
		
		cutController = (Dispatch)cut1xCom.getObject();
	
                events = new DispatchEvents(cutController,
                        new CutEvents(),
                        "optimal1dx.Optimization1DX");

	}


	public void putNumberOfDemandPieces(Integer value){
            Dispatch.put(cutController, "NumberOfDemandPieces", new Variant(value));
	}

        public void  putNumberOfRepositoryPieces(Integer value){
            Dispatch.put(cutController, "NumberOfRepositoryPieces", new Variant(value));
        }
        
        public void  putBladeWidth(Integer value){
            Dispatch.put(cutController, "BladeWidth", new Variant(value));
        }

        public void  putOptimizationLevel(Integer value){
            Dispatch.put(cutController, "OptimizationLevel", new Variant(value));
        }

        public void  putRandomSeed(Integer value){
            Dispatch.put(cutController, "RandomSeed", new Variant(value));
        }

        public String getTotalNumberOfUtilizedRepositoryPieces(){
            Variant res = Dispatch.get(cutController, "TotalNumberOfUtilizedRepositoryPieces");
            return res.toString();
        }

        public void setDemandPiece(Integer index, Integer length, Double Angle1, Double Angle2, Integer externalId){
            Dispatch.call(cutController, "setDemandPiece", new Variant(index), new Variant(length), new Variant(Angle1),
                    new Variant(Angle2), new Variant(externalId));
        }

        public void setRepositoryPiece(Integer index, Integer length, Integer ExternalID){
            Variant[] args = new Variant[3]; // another way to send data ... usefull if you have more than 9 parameters to a function
            int i=0;
            args[i++] = new Variant(index);
            args[i++] = new Variant(length); 
            args[i++] = new Variant(ExternalID);


            Dispatch.callN(cutController, "SetRepositoryPiece", args);
        }



        public NumberOfUtilizedPiecesObject getNumberOfUtilizedPieces(Integer BarIndex){
        	NumberOfUtilizedPiecesObject numpieces = new NumberOfUtilizedPiecesObject();
        	
        	Dispatch.call(cutController, "GetNumberOfUtilizedDemandPieces", BarIndex, numpieces.numberOfUtilizedPieces, numpieces.repositoryIndex, numpieces.repositoryExternalID);
        	
        	return numpieces;
        }

        public RepositoryPieceObject getRepositoryPiece(Integer Index){
        	RepositoryPieceObject repositoryPiece = new RepositoryPieceObject ();
        	
        	Dispatch.call(cutController, "GetRepositoryPiece", Index, repositoryPiece.length, repositoryPiece.repositoryExternalID);
        	
        	return repositoryPiece ;
        }


        public DemandPieceObject getDemandPiece(Integer Index){
        	DemandPieceObject demandPiece = new DemandPieceObject ();
        	
        	Dispatch.call(cutController, "GetDemandPiece", Index, demandPiece.length, demandPiece.angle1, demandPiece.angle2, demandPiece.demandExternalID);
        	
        	return demandPiece ;
        }
        

        public UtilizedPiecesObject getUtilizedDemandPiece(Integer BarIndex, Integer PieceIndex){
        	UtilizedPiecesObject utilizedPiece = new UtilizedPiecesObject ();
        	        	
            Variant[] args = new Variant[9];
            
            args[0] = new Variant(BarIndex);
            args[1] = new Variant(PieceIndex);
            
            for (int i = 2; i < 9; i++)
            	args[i] = new Variant(new Integer(0), true);
        	
        	Dispatch.callN(cutController, "GetUtilizedDemandPiece", args);

        	utilizedPiece.repositoryIndex = args[2];
        	utilizedPiece.demandIndex = args[3];
        	utilizedPiece.rotatedOx = args[4];
        	utilizedPiece.rotatedOy = args[5];
        	utilizedPiece.rotatedOz = args[6];
        	utilizedPiece.repositoryExternalID = args[7];
        	utilizedPiece.demandExternalID = args[8];


        	return utilizedPiece;
        }


        public WasteObject getWaste(Integer BarIndex){
        	WasteObject waste = new WasteObject ();
        	
        	Dispatch.call(cutController, "GetWaste", BarIndex, waste.length, waste.repositoryIndex, waste.repositoryExternalID);
        	
        	return waste ;
        }


        public void startOptimization(){
             Dispatch.call(cutController, "Start");
        }



        public class CutEvents {
		public void OnFinish (Variant[] args) {
			System.out.println("---------------------------------------");
			Variant totalNumberOfUtilizedRepositoryPieces = Dispatch.get(cutController, "TotalNumberOfUtilizedRepositoryPieces");

			System.out.println("Number of bars: " + totalNumberOfUtilizedRepositoryPieces.getInt());
			System.out.println("---------------------------------------");

			// now for each bar
			for (int BarIndex = 0; BarIndex < totalNumberOfUtilizedRepositoryPieces.getInt(); BarIndex++){
				System.out.println("Bar: #" + BarIndex);
				UtilizedPiecesObject utilizedDemandPiece = getUtilizedDemandPiece(BarIndex, 0); // first piece in the bar

				RepositoryPieceObject repositoryPiece = getRepositoryPiece(utilizedDemandPiece.getRepositoryIndex());

				System.out.print( "(Length = " + repositoryPiece.getLength() + ")");

				NumberOfUtilizedPiecesObject numberOfUtilizedPieces = getNumberOfUtilizedPieces(BarIndex);
				for (int PieceIndex = 0; PieceIndex < numberOfUtilizedPieces.getNumberOfUtilizedPieces(); PieceIndex++){
					utilizedDemandPiece = getUtilizedDemandPiece(BarIndex, PieceIndex);

					DemandPieceObject demandPiece = getDemandPiece(utilizedDemandPiece.getDemandIndex());
					double a1 = demandPiece.getAngle1();
					double a2 = demandPiece.getAngle2();

					if (utilizedDemandPiece.getRotatedOx() == 1){
						a1 = 180 - a1;
						a2 = 180 - a2;
					}
					if (utilizedDemandPiece.getRotatedOy() == 1){
					        double tmp = a1;
					        a1 = 180 - a2;
					        a2 = 180 - tmp;
					}
					if (utilizedDemandPiece.getRotatedOz() == 1){
						double tmp = a1;
						a1 = a2;
						a2 = tmp;
					}
					System.out.print( "(" + demandPiece.getLength() + "," + a1 + "," + a2 + ")");
		
				}
	
				WasteObject waste = getWaste(BarIndex);
    				System.out.println("(Waste = " + waste.getLength() + ")");
				System.out.println("--------------------------------");
			}
		}
	}        

       public class NumberOfUtilizedPiecesObject { 
     	   	 public Variant numberOfUtilizedPieces = new Variant(new Integer(0), true);  
     	   	 public Variant repositoryIndex = new Variant(new Integer(0), true); 
     	   	 public Variant repositoryExternalID = new Variant(new Integer(0), true);
     	   	    	   	
     	   	 public int getNumberOfUtilizedPieces(){
     	   		return numberOfUtilizedPieces.getIntRef();
     	   	 }    	   
         }

       public class UtilizedPiecesObject { 
     	   	 public Variant repositoryIndex = new Variant(new Integer(0), true);  
     	   	 public Variant demandIndex = new Variant(new Integer(0), true);  
     	   	 public Variant rotatedOx = new Variant(new Integer(0), true);  
     	   	 public Variant rotatedOy = new Variant(new Integer(0), true);  
     	   	 public Variant rotatedOz = new Variant(new Integer(0), true);  
     	   	 public Variant repositoryExternalID = new Variant(new Integer(0), true);
     	   	 public Variant demandExternalID = new Variant(new Integer(0), true); 
     	   	    	   	
     	   	 public int getRepositoryIndex(){
     	   		return repositoryIndex.getIntRef();
     	   	 }    	   
     	   	 public int getDemandIndex(){
     	   		return demandIndex.getIntRef();
     	   	 }    	   
     	   	 public int getRotatedOx(){
     	   		return rotatedOx.getIntRef();
     	   	 }    	   
     	   	 public int getRotatedOy(){
     	   		return rotatedOy.getIntRef();
     	   	 }    	   
     	   	 public int getRotatedOz(){
     	   		return rotatedOz.getIntRef();
     	   	 }    	   
         }
      
       public class DemandPieceObject { 
     	   	 public Variant length = new Variant(new Integer(0), true);  
     	   	 public Variant angle1 = new Variant(new Double(90), true);  
     	   	 public Variant angle2 = new Variant(new Double(90), true);  
     	   	 public Variant demandExternalID = new Variant(new Integer(0), true); 
     	   	    	   	
     	   	 public int getLength(){
     	   		return length.getIntRef();
     	   	 }    	   
     	   	 public double getAngle1(){
     	   		return angle1.getDoubleRef();
     	   	 }    	   
     	   	 public double getAngle2(){
     	   		return angle2.getDoubleRef();
     	   	 }    	   
         }

       public class RepositoryPieceObject { 
     	   	 public Variant length = new Variant(new Integer(0), true);  
     	   	 public Variant repositoryExternalID = new Variant(new Integer(0), true); 
     	   	    	   	
     	   	 public int getLength(){
     	   		return length.getIntRef();
     	   	 }    	   
         }

       public class WasteObject { 
     	   	 public Variant length = new Variant(new Double(0), true);  
     	   	 public Variant repositoryIndex = new Variant(new Integer(0), true); 
     	   	 public Variant repositoryExternalID = new Variant(new Integer(0), true); 
     	   	    	   	
     	   	 public double getLength(){
     	   		return length.getDoubleRef();
     	   	 }    	   
         }

        private void runTest(){
            putNumberOfDemandPieces(10);

            setDemandPiece(0, 2, 90.0, 90.0, 0);
            setDemandPiece(1, 2, 90.0, 90.0, 1);
            setDemandPiece(2, 2, 90.0, 90.0, 2);
            setDemandPiece(3, 2, 90.0, 90.0, 3);
            setDemandPiece(4, 2, 90.0, 90.0, 4);
            setDemandPiece(5, 7, 90.0, 90.0, 5);
            setDemandPiece(6, 7, 90.0, 90.0, 6);
            setDemandPiece(7, 7, 90.0, 90.0, 7);
            setDemandPiece(8, 7, 90.0, 90.0, 8);
            setDemandPiece(9, 7, 90.0, 90.0, 9);

            putNumberOfRepositoryPieces(6);

            setRepositoryPiece(0, 10, 0);
            setRepositoryPiece(1, 10, 1);
            setRepositoryPiece(2, 10, 2);
            setRepositoryPiece(3, 10, 3);
            setRepositoryPiece(4, 10, 4);
            setRepositoryPiece(5, 10, 5);

            putBladeWidth(0);
            putOptimizationLevel(50);
            putRandomSeed(1);

            startOptimization();

        }


	public static void main(String args[]) throws Exception {
            try{
		CutTest test = new CutTest();

                test.runTest();
            } catch(ComFailException e){
                System.out.println("ups!");
                e.printStackTrace();
            }finally {
                ComThread.Release();
            }
                

	}

} 