package cse605;
import java.awt.*;
import java.awt.geom.*;
import java.awt.font.*;
import java.io.*;
import java.lang.ref.*;
import java.util.*;

abstract class ElecComponent extends Component implements Edge, Cloneable, Serializable
{
    String ID;
//    String I;
    boolean currentCenterCheck = false;
    String value;
    String Ival;
    static int Icount;
    String Iid;
    public Node l_node, r_node;
    protected LinkedList instanceConstraints = new LinkedList();
    protected boolean prevPainted = false;
    protected boolean isPicked;
    public transient Shape center;
    
    public String getID(){
        return ID;
    }
    
    public void exchangeNode(Node n, int whichNode, String flag) {

        if(whichNode == RIGHT_NODE){
            for(int i=0; i<r_node.edges.size(); i++){
                if( ((Edge)r_node.edges.get(i)).getID().equals(ID)){
                    if(flag.equals("add")) n.edges.add(this);
                    r_node = n;
                    return;
                }
                //ERROR element should have been found here.
            }//end for

        }
        else if(whichNode == LEFT_NODE){ 
            for(int i=0; i<l_node.edges.size(); i++){
                if(((String)((Edge)l_node.edges.get(i)).getID()).equals(ID)){
                    if(flag.equals("add")) n.edges.add(this);
                    l_node = n;
                    return;
                }
                //ERROR element should have been found here.
            }//end for

        }

        if(whichNode == RIGHT_NODE){ 
             if(flag.equals("add")) n.edges.add(this);
             r_node = n;
        }
        else if(whichNode == LEFT_NODE){ 
             if(flag.equals("add")) n.edges.add(this);
             l_node = n;
        }        
        
    }
    
    public Node[] getNodes() {
        Node[] nodes = {l_node, r_node };
        return nodes;
    }
    
    public ElecComponent getClone(){
        try{
            return (ElecComponent)clone();
        }
        catch(CloneNotSupportedException cnse){//error message
        }
        return null;
    }
    
    public void assignCurrent(String ival)
    {
        Ival = ival;
    }

    public String getCurrent() {
    	if(Ival ==null || Ival.equals("?")) return Iid;
    	else if(Ival ==null || Ival.equals("")) return Iid;
        else return Ival;
    }

    public String getCurrentID() {
        return Iid;
    }

    public int getCurrIDVal() {
	return Integer.parseInt(Iid.substring(1));
    }
    
    public static void setCurrCount(int val)
    {
    	Icount = val;    
    }

    public static int getIcount()
    {
      return Icount;
    }
  
    public void passCurrentToNodes()
    {
    	String val;
	if(Ival == null || Ival.equals("?") || Ival.equals("") ) val = Iid;
	else val = Ival;
        l_node.assignCurrent(val, this);
        r_node.assignCurrent("-"+val, this);
    }
    
    public void adjustNodes()
    {
        if(l_node.x > r_node.x)//swap thw nodes
        {
            Node temp = (Node)(new WeakReference(r_node)).get() ;
            r_node = l_node;
            l_node = temp;
        }
    }
    
    public void showVals(Graphics g)
    {
        adjustNodes();
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);

        g2.setRenderingHint(RenderingHints.KEY_RENDERING,
                            RenderingHints.VALUE_RENDER_QUALITY);
	/*
        String s;
        if(ID.startsWith("W")) s = I +"\t"+ ID ; 
        else s = new String(Iid ); 
	*/
        DrawingUtility.showVals(l_node.x + Node.w/2, l_node.y+Node.h/2, r_node.x+Node.w/2, r_node.y+Node.h/2 ,g2, Iid);
    }

    public void showID(Graphics g)
    {
        adjustNodes();
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);

        g2.setRenderingHint(RenderingHints.KEY_RENDERING,
                            RenderingHints.VALUE_RENDER_QUALITY);
	int dist = (int)Math.pow((Math.pow((r_node.x-l_node.x),2)+Math.pow((r_node.y-l_node.y),2)),0.5) ;
        int fontSize =(int)(dist/4) ;
        if(fontSize>12) fontSize = 12;
        if(fontSize <6) fontSize = 8;
        int fontStyle ;
        if(fontSize<9) fontStyle = Font.BOLD ;
        else fontStyle = Font.PLAIN;
        FontRenderContext frc = g2.getFontRenderContext();
        Font f = new Font("Times", fontStyle, fontSize);
        String s = new String(ID);
        TextLayout tl = new TextLayout(s, f, frc);
        DrawingUtility.showID(l_node.x + Node.w/2, l_node.y+Node.h/2, r_node.x+Node.w/2, r_node.y+Node.h/2 ,g2, tl);
    }

    
    public String getValue() {
    	if( value == null ) return "";
    	else if( value.equals("?") || value.equals("") ) return ID ;
//    	else if( value.equals("?")) return ID + "x";
        else return value;
    }

    public void setValue(String val)
    {
      value = val;
    }
    
    public boolean bothEndsSelected() {
        if(l_node.isSelected && r_node.isSelected) return true;
        else return false;
    }

    public void adjustCenter(){
        double dist = Math.sqrt( Math.pow((l_node.x-r_node.x),2) + Math.pow((l_node.y-r_node.y),2) );        
        float x = (float)(l_node.x + 0.35*dist );
        float y = (float)(l_node.y - 0.1*dist );
        float w = (float)(0.3*dist);
        float h = (float)(0.2*dist);
        Shape temp = new Ellipse2D.Float(x,y,w,h);
        double phi = Math.atan((r_node.y - l_node.y)/(r_node.x - l_node.x) ) ;
        AffineTransform at = new AffineTransform() ;
        at.rotate(phi, l_node.x, l_node.y);    
        center  =  at.createTransformedShape(temp) ;
    }
    
    public boolean centerSelected(int x, int y, boolean leftClicked) {
        boolean selected = center.contains(x,y);
/*
 *  if rightClicked
 */        
        if(!leftClicked){
            return selected ;
        }        

/*
 *  if left clicked :
 *
 */        
        if(currentCenterCheck) {
            currentCenterCheck = false;
            return false;
        }
        else currentCenterCheck = true;
            
        if(selected){
            if( l_node.isSelected && r_node.isSelected ){
                l_node.disSelect();
                r_node.disSelect();
                l_node.isDraggable = false;            
                r_node.isDraggable = false;            
                l_node.unsetToMove();
                r_node.unsetToMove();
            }
            else{
                l_node.select();
                r_node.select();
                l_node.isDraggable = true;            
                r_node.isDraggable = true;
            }
        }
        return selected;
    }

    public abstract String getType();
    public abstract void picked(Graphics g);
    public abstract void draw(Graphics g);
    public abstract void basicDraw(Graphics g);
    
    public void pickdraw(Graphics g)
    {
   	if(isPicked) picked(g);
    }
    
    public void clearPick()
    {
    	isPicked =false;
    }
    
/*
    public String getType() {
        if(ID.startsWith("R")) return "Resistor";
        else if(ID.startsWith("B")) return "Battery";
        else if(ID.startsWith("W")) return "Wire";
        else return "";
    }
*/

    public int getIDVal() {
        return Integer.parseInt(ID.substring(1)) ; 
    }
    
    public int getCurrentValue() {
        return -1;
    }
    
    public String[] getInstanceConstraint() {
        String[] list = new String[instanceConstraints.size()];
        for(int i=0 ; i < list.length; i++)
            list[i] = (String)instanceConstraints.get(i);
        return list ;
    }
    
    public void addInstanceConstriant(String constraint) {
        instanceConstraints.add(constraint);
    }

    public void removeAllInstanceConstriant() {
        instanceConstraints.clear();
    }

    
    
}


