/*
 * Created on 09.09.2004
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package TUGLaby;

import java.awt.Color;
import java.awt.datatransfer.DataFlavor;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.LinkedList;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;

/**
 * @author auguan@sbox
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class ConditionRulePanel extends JPanel {

    /**
     * 
     */
    private RuleTreePanel parent_panel_;
    private SensorChoosePanel left_sensor_;
    private SensorChoosePanel right_sensor_;
    private SensorChoosePanel ahead_sensor_;
    private CurrentSensorPanel current_sensor_;
    private ConditionChoosePanel cond_panel_;
    

    private JCheckBox active_switch_;
    private JButton delete_button_;
    private HashMap brick_images_;
    
    /** Drop related classes */
    private DropRuleListener drop_rule_listener_;
    private DropTarget drop_target_;
    private int acceptable_actions_ = DnDConstants.ACTION_COPY;
    
    private int id_;
    ActionRulePanel new_action_; 
    private boolean action_added_;
    
    
    public ConditionRulePanel() {
        super();
        this.setLayout(null);
        drop_rule_listener_ = new DropRuleListener();
        drop_target_ = new DropTarget(this, this.acceptable_actions_,
        this.drop_rule_listener_, true);
        action_added_ = false;
    } 
    public ConditionRulePanel( int id, RuleTreePanel parent_panel , HashMap brick_images ) {

        super();
        this.setLayout( null );
        action_added_ = false;
        id_ = id;
        parent_panel_ = parent_panel;
        drop_rule_listener_ = new DropRuleListener();
        drop_target_ = new DropTarget(this, this.acceptable_actions_,
        this.drop_rule_listener_, true);
        brick_images_ = brick_images;
        JLabel top_label = new JLabel();
        JLabel csensor_label = new JLabel();
        left_sensor_ = new SensorChoosePanel(brick_images);
        right_sensor_ = new SensorChoosePanel(brick_images);
        ahead_sensor_ = new SensorChoosePanel(brick_images);
        cond_panel_ = new ConditionChoosePanel(brick_images);
        current_sensor_ = new CurrentSensorPanel(brick_images);
        active_switch_ = new JCheckBox();
        delete_button_ = new JButton();
        
        this.add( top_label );
        this.add( left_sensor_ );
        this.add( right_sensor_ );
        this.add( ahead_sensor_ );
        this.add( csensor_label );       
        this.add( current_sensor_ );
        this.add( active_switch_ );
        this.add( delete_button_ );
        this.add( cond_panel_);
        left_sensor_.setBounds( 10,40,20,20 );
        ahead_sensor_.setBounds( 32,18,20,20 );
        right_sensor_.setBounds( 54,40,20,20 );
        current_sensor_.setBounds( 32, 40,20,20);
        cond_panel_.setBounds(27,62,30,15 );
        
        top_label.setText("Sensorregel:");
        //top_label.setForeground( Color.white );
        
        //csensor_label.setText("Bodensensor:");
  
        top_label.setBounds(5,2,150,15);    
        active_switch_.setBounds(210,2,20,20);
        active_switch_.setOpaque( false );
        active_switch_.setSelected( true );
        
        delete_button_.setBounds( 230,6,13,13);
        delete_button_.setOpaque( false );
        delete_button_.setIcon( (ImageIcon) brick_images_.get("X_BUTTON") );
        
        
        this.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED));
        this.setBackground( Color.red );
        initActionListener();
    }
    
    public int getID()
    {
        return id_;
    }
    
    private void initActionListener()
    {
        active_switch_.addActionListener(new java.awt.event.ActionListener()
                {
                  public void actionPerformed(java.awt.event.ActionEvent evt)
                  {
                    if( active_switch_.isSelected() )
                        ConditionRulePanel.this.setBackground( Color.RED );
                    else
                        ConditionRulePanel.this.setBackground( Color.DARK_GRAY );
                  }
                });
        delete_button_.addActionListener(new java.awt.event.ActionListener()
                {
                  public void actionPerformed(java.awt.event.ActionEvent evt)
                  {
                     parent_panel_.deleteRule( id_ );
                  }
                });
        
    }
    
    public String getInfo()
    {
        if(active_switch_.isSelected() )
        {
	        String output = left_sensor_.getInternalState() + ":" + ahead_sensor_.getInternalState()
	                        + ":" +right_sensor_.getInternalState()+"::"+current_sensor_.getInternalState()
	                        +"["+cond_panel_.getInternalState()+"]";
	        
	        if( action_added_ )
	            output += " >> " + new_action_.getInfo();
	        return output;
        }
        else
            return "";
    }
    public void addAction( String name )
    {
      
      if( name.compareTo("ConditionRule") == 0 )
      {
         //System.out.println("Depp bläder"); 
      }
      else
      {
         if( !action_added_ )
         {
	         new_action_ = new ActionRulePanel(name, brick_images_);
	         this.add( new_action_ );
	         new_action_.setBounds( 80,25,165,60);
	         action_added_=true;
         }
      }
    }
    
    public class DropRuleListener implements DropTargetListener {

        /**
         * Called by isDragOk Checks to see if the flavor drag flavor is
         * acceptable
         * 
         * @param e
         *            the DropTargetDragEvent object
         * @return whether the flavor is acceptable
         */
        private boolean isDragFlavorSupported(DropTargetDragEvent e) {
            boolean ok = false;
            if (e.isDataFlavorSupported(DataFlavor.stringFlavor)) {
                ok = true;
            } else if (e.isDataFlavorSupported(DataFlavor.plainTextFlavor)) {
                ok = true;
            }
            return ok;
        }

        /**
         * Called by drop Checks the flavors and operations
         * 
         * @param e
         *            the DropTargetDropEvent object
         * @return the chosen DataFlavor or null if none match
         */
        private DataFlavor chooseDropFlavor(DropTargetDropEvent e) {
            DataFlavor chosen = null;
            if (e.isLocalTransfer() == true )
              if (e.isDataFlavorSupported(DataFlavor.stringFlavor)) {
                chosen = DataFlavor.stringFlavor;
            } else if (e.isDataFlavorSupported(DataFlavor.plainTextFlavor)) {
                chosen = DataFlavor.plainTextFlavor;
            }
            return chosen;
        }

        /**
         * Called by dragEnter and dragOver Checks the flavors and operations
         * 
         * @param e
         *            the event object
         * @return whether the flavor and operation is ok
         */
        private boolean isDragOk(DropTargetDragEvent e) {
            if (isDragFlavorSupported(e) == false) {
                // System.out.println( "isDragOk:no flavors chosen" );
                return false;
            }
            int da = e.getDropAction();
            // System.out.print("dt drop action " + da);
            // System.out.println(" my acceptable actions " +
            // acceptable_actions_);
            if ((da & ConditionRulePanel.this.acceptable_actions_) == 0)
                return false;
            return true;
        }

        /**
         * start "drag under" feedback on component invoke acceptDrag or
         * rejectDrag based on isDragOk
         */
        public void dragEnter(DropTargetDragEvent e) {
            // System.out.println( "dtlistener dragEnter");
            if (isDragOk(e) == false) {
                // System.out.println( "enter not ok");
                // CODE HERE if bad
                e.rejectDrag();
                return;
            }
            // CODE HERE if good
            // System.out.println( "dt enter: accepting " + e.getDropAction());
            e.acceptDrag(e.getDropAction());
        }

        /**
         * continue "drag under" feedback on component invoke acceptDrag or
         * rejectDrag based on isDragOk
         */
        public void dragOver(DropTargetDragEvent e) {
            if (isDragOk(e) == false) {
                // System.out.println( "dtlistener dragOver not ok" );
                // CODE IF NESSECARY
                e.rejectDrag();
                return;
            }
            // System.out.println( "dt over: accepting");
            e.acceptDrag(e.getDropAction());
        }

        public void dropActionChanged(DropTargetDragEvent e) {
            if (isDragOk(e) == false) {
                // System.out.println( "dtlistener changed not ok" );
                e.rejectDrag();
                return;
            }
            // System.out.println( "dt changed: accepting"+e.getDropAction());
            e.acceptDrag(e.getDropAction());
        }

        public void dragExit(DropTargetEvent e) {
            // System.out.println( "dtlistener dragExit");
        }

        /**
         * perform action from getSourceActions on the transferrable invoke
         * acceptDrop or rejectDrop invoke dropComplete if its a local (same
         * JVM) transfer, use StringTransferable.localStringFlavor find a match
         * for the flavor check the operation get the transferable according to
         * the chosen flavor do the transfer
         */
        public void drop(DropTargetDropEvent e) {
            // System.out.println( "dtlistener drop");
            DataFlavor chosen = chooseDropFlavor(e);
            if (chosen == null) {
                // System.err.println( "No flavor match found" );
                e.rejectDrop();
                return;
            }
            // System.err.println( "Chosen data flavor is " +
            // chosen.getMimeType());
            int da = e.getDropAction();
            int sa = e.getSourceActions();
            // System.out.println( "drop: sourceActions: " + sa);
            // System.out.println( "drop: dropAction: " + da);

            if ((sa & ConditionRulePanel.this.acceptable_actions_) == 0) {
                // System.err.println( "No action match found" );
                e.rejectDrop();
                // CODE
                return;
            }

            Object data = null;
            try {
                e.acceptDrop(ConditionRulePanel.this.acceptable_actions_);
                data = e.getTransferable().getTransferData(chosen);
                if (data == null)
                    throw new NullPointerException();
            } catch (Throwable t) {
                // System.err.println( "Couldn't get transfer data: " +
                // t.getMessage());
                t.printStackTrace();
                e.dropComplete(false);
                // Bad transdata
                return;
            }
            // System.out.println( "Got data: " + data.getClass().getName() );

            if (data instanceof String) {
                String s = (String) data;
                //DropLabel.this.setText(s);
                
               // TODO ACTION
                ConditionRulePanel.this.addAction(s);
                
            } else if (data instanceof InputStream) {
                InputStream input = (InputStream) data;
                InputStreamReader isr = null;
                //	BufferedReader br = null;
                try {
                    // br = new BufferedReader(isr=new
                    // InputStreamReader(input,"Unicode"));
                    isr = new InputStreamReader(input, "Unicode");
                } catch (UnsupportedEncodingException uee) {
                    isr = new InputStreamReader(input);
                }

                StringBuffer str = new StringBuffer();
                int in = -1;
                try {
                    while ((in = isr.read()) >= 0) {
                        //// System.out.println("read: " + in);
                        if (in != 0)
                            str.append((char) in);
                    }

                    /*
                     * you get garbage chars this way try { String line=null;
                     * while( (line = br.readLine()) != null) {
                     * str.append(line); str.append('\n'); //
                     * System.out.println( "read: " + line); //
                     * System.out.println( "read: " +
                     * (int)line.charAt(line.length()-1)); }
                     * 
                     * br.close();
                     */
                    // CODE HERE DATA FROM STREAM
                    //DropLabel.this.setText(str.toString());
                } catch (IOException ioe) {
                    /*
                     * bug #4094987 sun.io.MalformedInputException: Missing
                     * byte-order mark e.g. if dragging from MS Word 97 still a
                     * bug in 1.2 final
                     */

                    // System.err.println( "cannot read" + ioe);
                    e.dropComplete(false);

                    String message = "Bad drop\n" + ioe.getMessage();
                    // System.err.println(message);
                }

            } else {
                // System.out.println( "drop: rejecting");
                e.dropComplete(false);

                return;
            }

            e.dropComplete(true);

        }

    }
    
}
