function PCB(containerID){
    
    /* CALCULATED INFO */
    this.maxArrays=0;
    this.maxPartsPerArray=0;
    this.maxParts=0;
    
    this.infoBoxWidth=300;
    this.pixelsToInch=20;
    
    this.multipleParts=false;
    this.partsWidth=1;
    this.partsHeight=1;
    
    this.PanelWidth=18;
    this.PanelHeight=24;
    this.PanelLeftMargin=0.5;
    this.PanelRightMargin=0.5;
    this.PanelTopMargin=0.5;
    this.PanelBottomMargin=0.5;
    this.panelSpacing=0.1;
    
    this.calculateArrays=false;
    this.ArrayWidth=4;
    this.ArrayHeight=4;
    this.ArrayLeftMargin=0.5;
    this.ArrayRightMargin=0.5;
    this.ArrayTopMargin=0.5;
    this.ArrayBottomMargin=0.5;
    this.arraySpacing=0.1;
    
    this.firstArray=null;
    
    this.processing=false;
    
    this.container=document.getElementById(containerID);
}

// Calculate Panel Width
PCB.prototype.calculatePanelWidth = function(fullwidth){
    if(fullwidth==undefined) fullwidth=false;

    var width=this.PanelWidth;
    if(this.PanelLeftMargin!==null){
        width-=this.PanelLeftMargin;
    }
    if(this.PanelRightMargin!==null){
        width-=this.PanelRightMargin;
    }
    
    //if(!fullwidth && this.multipleParts) width=width/this.partsWidth.length;
    
    return width;
}

// Calculate Panel Height
PCB.prototype.calculatePanelHeight = function(fullheight){
    if(fullheight==undefined) fullheight=false;
    var height=this.PanelHeight;
    height-=this.PanelTopMargin;
    height-=this.PanelBottomMargin;

    if(!fullheight && this.multipleParts) height=height/this.partsHeight.length;
    
    return height;
}

// calculate dimensions and render panel
PCB.prototype.renderPanel = function(){
    this.container.innerHTML='';
    this.panel=document.createElement("div");
    this.container.appendChild(this.panel);
    
    if(this.PanelWidth > 30){
        this.pixelsToInch = 20*30/this.PanelWidth;
    }
    
    this.panel.style.cssFloat="left";
    this.panel.style.styleFloat="left";
    this.panel.style.background="PaleGreen";
    this.panel.id="PCB_panel";
    this.panel.style.position="relative";
    this.panel.style.width=(this.calculatePanelWidth(true)*this.pixelsToInch)+"px";
    this.panel.style.height=(this.calculatePanelHeight(true)*this.pixelsToInch)+"px";
    this.panel.style.borderStyle="solid";
    this.panel.style.borderColor="burlywood";
    this.panel.style.borderLeftWidth=(this.PanelLeftMargin*this.pixelsToInch)+"px";
    this.panel.style.borderRightWidth=(this.PanelRightMargin*this.pixelsToInch)+"px";
    this.panel.style.borderTopWidth=(this.PanelTopMargin*this.pixelsToInch)+"px";
    this.panel.style.borderBottomWidth=(this.PanelBottomMargin*this.pixelsToInch)+"px";
    
    var overlay = document.createElement("div");
    overlay.innerHTML = "<img src='"+overlayImage+"' width='100%' >";
    overlay.id="PCB_panel_overlay";
    this.panel.appendChild(overlay);
}

// Calculate Array Width
PCB.prototype.calculateArrayWidth = function(){
    var width=this.ArrayWidth;
    width-=this.ArrayLeftMargin;
    width-=this.ArrayRightMargin;
    
    return width;
}

// Calculate Array Height
PCB.prototype.calculateArrayHeight = function(){
    var height=this.ArrayHeight;
    height-=this.ArrayTopMargin;
    height-=this.ArrayBottomMargin;

    return height;
}

// calculate dimensions and render arrays
PCB.prototype.renderArrays = function(){
    var x=this.maxHorizontalArrays();
    var y=this.maxVerticalArrays();
    this.maxArrays=x*y;
    
    var offset_x=(this.calculatePanelWidth()-x*(this.ArrayWidth)-(x-1)*this.panelSpacing)/2;
    var offset_y=(this.calculatePanelHeight()-y*(this.ArrayHeight)-(y-1)*this.panelSpacing)/2;
    var posY=offset_y;
    for(var i=0;i<y;i++){
        var posX=offset_x;
        for(var j=0;j<x;j++){
            var array=document.createElement("div");
            array.style.position="absolute";
            array.style.width=(this.ArrayWidth*this.pixelsToInch-2)+"px";
            array.style.height=(this.ArrayHeight*this.pixelsToInch-2)+"px";
            array.style.top=(posY*this.pixelsToInch)+"px";
            array.style.left=(posX*this.pixelsToInch)+"px";
            array.style.background="grey";
            array.style.border="1px solid black";
            array.style.zIndex="50";
            this.panel.appendChild(array);
            if(this.firstArray===null) this.firstArray=array;
           
            posX+=(this.ArrayWidth+this.panelSpacing);
        }
        
        posY+=(this.ArrayHeight+this.panelSpacing);
  
    }
}

// Get max number of arrays that can fit into vertical space
PCB.prototype.maxVerticalArrays =function(){
    var height=this.calculatePanelHeight();
    var ArrayHeight=this.ArrayHeight;
    height-=this.panelSpacing;
    ArrayHeight+=this.panelSpacing;

    return Math.floor(height/ArrayHeight);
}

// Get max number of arrays that can fit into horizontal space
PCB.prototype.maxHorizontalArrays =function(){
    var width=this.calculatePanelWidth();
    var ArrayWidth=this.ArrayWidth;
    width-=this.panelSpacing;
    ArrayWidth+=this.panelSpacing;

    return Math.floor(width/ArrayWidth);
}

// Get max number of boards that can fit into vertical space
PCB.prototype.maxVerticalParts =function(index){
    var height=this.calculateArrays?this.calculateArrayHeight():this.calculatePanelHeight();
    var partHeight=index!=undefined?this.partsHeight[index]:this.partsHeight;
    height-=this.calculateArrays?this.arraySpacing:this.panelSpacing;
    partHeight+=this.calculateArrays?this.arraySpacing:this.panelSpacing;

    return Math.floor(height/partHeight);
}

// Get max number of boards that can fit into horizontal space
PCB.prototype.maxHorizontalParts =function(index){
    var width=this.calculateArrays?this.calculateArrayWidth():this.calculatePanelWidth();
    var partWidth=index!=undefined?this.partsWidth[index]:this.partsWidth;
    width-=this.calculateArrays?this.arraySpacing:this.panelSpacing;
    partWidth+=this.calculateArrays?this.arraySpacing:this.panelSpacing;

    return Math.floor(width/partWidth);
}

// calculate dimensions and render all parts
PCB.prototype.renderParts = function(){
    
    var x=this.maxHorizontalParts();
    var y=this.maxVerticalParts();
    var offset_x,offset_y,posY,posX,x,y,part;
    
    if(this.multipleParts){
        
        this.maxParts=new Array();
        
        for(var k=0;k<this.partsWidth.length;k++){
            x=this.maxHorizontalParts(k);
            y=this.maxVerticalParts(k);
            
            offset_x=(this.calculatePanelWidth()-x*(this.partsWidth[k]+this.panelSpacing)-this.panelSpacing)/2 ;
            offset_y=(this.calculatePanelHeight()-y*(this.partsHeight[k]+this.panelSpacing)-this.panelSpacing)/2 + k*this.calculatePanelHeight();
           
            this.maxParts.push(x*y);
            
            posY=this.panelSpacing+offset_y;

            for(var i=0;i<y;i++){
                posX=this.panelSpacing+offset_x;
                ;
                for(var j=0;j<x;j++){
                    part=document.createElement("div");
                    part.style.position="absolute";
                    part.style.width=(this.partsWidth[k]*this.pixelsToInch-2)+"px";
                    part.style.height=(this.partsHeight[k]*this.pixelsToInch-2)+"px";
                    part.style.top=(posY*this.pixelsToInch)+"px";
                    part.style.left=(posX*this.pixelsToInch)+"px";
                    part.style.background="Green";
                    part.style.border="1px solid black";
                    part.style.zIndex="100";
                    this.panel.appendChild(part);
                    posX+=(this.partsWidth[k]+this.panelSpacing);
                }
                posY+=(this.partsHeight[k]+this.panelSpacing);
            }
            
        }
        
    }
    else  if(this.calculateArrays){
        
        x=this.maxHorizontalParts();
        y=this.maxVerticalParts();
    
        offset_x=this.ArrayLeftMargin+(this.calculateArrayWidth()-x*(this.partsWidth+this.arraySpacing)-this.arraySpacing)/2 ;
        offset_y=this.ArrayTopMargin+(this.calculateArrayHeight()-y*(this.partsHeight+this.arraySpacing)-this.arraySpacing)/2 ;
        
        this.maxPartsPerArray=x*y;
        this.maxParts=this.maxArrays*this.maxPartsPerArray;
        
        posY=this.arraySpacing+offset_y;
    
        for(var i=0;i<y;i++){
            posX=this.arraySpacing+offset_x;
            ;
            for(var j=0;j<x;j++){
                part=document.createElement("div");
                part.style.position="absolute";
                part.style.width=(this.partsWidth*this.pixelsToInch-2)+"px";
                part.style.height=(this.partsHeight*this.pixelsToInch-2)+"px";
                part.style.top=(posY*this.pixelsToInch-1)+"px";
                part.style.left=(posX*this.pixelsToInch-1)+"px";
                part.style.background="Green";
                part.style.border="1px solid black";
                part.style.zIndex="100";
                this.firstArray.appendChild(part);
                posX+=(this.partsWidth+this.arraySpacing);
                
            }
            posY+=(this.partsHeight+this.arraySpacing);
        }
    
    }
    else {
        
        x=this.maxHorizontalParts();
        y=this.maxVerticalParts();
        
        offset_x=(this.calculatePanelWidth()-x*(this.partsWidth+this.panelSpacing)-this.panelSpacing)/2 ;
        offset_y=(this.calculatePanelHeight()-y*(this.partsHeight+this.panelSpacing)-this.panelSpacing)/2 ;
        this.maxParts=x*y;
        
        posY=this.panelSpacing+offset_y;
    
        for(var i=0;i<y;i++){
            posX=this.panelSpacing+offset_x;
            ;
            for(var j=0;j<x;j++){
                part=document.createElement("div");
                part.style.position="absolute";
                part.style.width=(this.partsWidth*this.pixelsToInch-2)+"px";
                part.style.height=(this.partsHeight*this.pixelsToInch-2)+"px";
                part.style.top=(posY*this.pixelsToInch)+"px";
                part.style.left=(posX*this.pixelsToInch)+"px";
                part.style.background="Green";
                part.style.border="1px solid black";
                part.style.zIndex="100";
                this.panel.appendChild(part);
                posX+=(this.partsWidth+this.panelSpacing);
            }
            posY+=(this.partsHeight+this.panelSpacing);
        }
    }
    
    part=null;
    
   
}

PCB.prototype.getPanelUtilization = function(){
    var utilization=0;
    
    if(this.multipleParts){
        
        var surface=0;
        
        for(var i=0;i<this.maxParts.length;i++){
            surface += ( this.maxParts[i] * this.partsWidth[i] * this.partsHeight[i] );
       
        
        }
        utilization=surface/(this.PanelHeight*this.PanelWidth);
    }
    else if(this.calculateArrays){ 
        utilization=(this.maxArrays*this.ArrayWidth*this.ArrayHeight)/(this.PanelHeight*this.PanelWidth);
    }
    else {
        utilization=(this.maxParts*this.partsWidth*this.partsHeight)/(this.PanelHeight*this.PanelWidth);
    }
    
    return (utilization*100).toFixed(1);
}

PCB.prototype.getArrayUtilization = function(){
    var utilization=0;
    
    utilization=(this.maxPartsPerArray*this.partsWidth*this.partsHeight)/(this.ArrayHeight*this.ArrayWidth);
    
    return (utilization*100).toFixed(1);
}

// display info about rendered PCB board
PCB.prototype.displayInfo = function(){
    var infoBox = document.createElement("div");
    this.container.appendChild(infoBox);
    infoBox.style.width=this.infoBoxWidth+"px";
    infoBox.style.position="relative";
    infoBox.style.cssFloat="left";
    infoBox.style.styleFloat="left";
    infoBox.style.padding="10px";
    
    var infoHTML="";
    
    infoHTML+="<b>Size</b><br/>";
    infoHTML+="<div style='padding-left:10px' >";
    infoHTML+="Panel: "+this.calculatePanelWidth(true).toFixed(4)+" X "+this.calculatePanelHeight(true).toFixed(4);
    infoHTML+="<br/>";
    if(this.calculateArrays){
        infoHTML+="Array: "+this.ArrayWidth.toFixed(4)+" X "+this.ArrayHeight.toFixed(4);
        infoHTML+="<br/>";
    }

    if(this.multipleParts){
        for(var i=0;i<this.maxParts.length;i++){
            infoHTML+="Part #"+(i+1)+": "+this.partsWidth[i].toFixed(4)+" X "+this.partsHeight[i].toFixed(4);
            infoHTML+="<br/>";
        }
    }
    else {
        infoHTML+="Part: "+this.partsWidth.toFixed(4)+" X "+this.partsHeight.toFixed(4);
    }
    infoHTML+="</div>";
    
    infoHTML+="<b>Panel Yield</b><br/>";
    infoHTML+="<div style='padding-left:10px' >";
    if(this.calculateArrays){
        infoHTML+=this.maxArrays+" Array"+(this.maxArrays==1?"":"s")+" of "+this.maxPartsPerArray+" Part"+(this.maxPartsPerArray==1?"":"s");
        infoHTML+="<br/>";
    }
    
    if(this.multipleParts){
        
        var totalParts=0;
        
        for(var i=0;i<this.maxParts.length;i++){
            infoHTML+="Part #"+(i+1)+": "+this.maxParts[i]+" Part"+(this.maxParts[i]==1?"":"s")+" Max";
            infoHTML+="<br/>";
            totalParts += this.maxParts[i];
        }
        infoHTML+=totalParts+" Part"+(totalParts==1?"":"s")+" Max Total";
    }
    else {
        infoHTML+=this.maxParts+" Part"+(this.maxParts==1?"":"s")+" Max Total";
    }
    
    infoHTML+="<br/>";
    infoHTML+=this.getPanelUtilization()+"% Panel Utilization";
    if(this.calculateArrays){
        infoHTML+="<br/>";
        infoHTML+=this.getArrayUtilization()+"% Array Utilization";
        
    }
    infoHTML+="</div>";
    
    infoHTML+="<b>Matrix</b><br/>";
    infoHTML+="<div style='padding-left:10px' >";
    if(this.multipleParts){
        
        for(var i=0;i<this.maxParts.length;i++){
            infoHTML+="Part #"+(i+1)+" On Panel: "+this.maxHorizontalParts(i)+" X "+this.maxVerticalParts(i);
            infoHTML+="<br/>";
            
        }
    }
    else if(this.calculateArrays){
        infoHTML+="On Panel: "+this.maxHorizontalArrays()+" X "+this.maxVerticalArrays();
        infoHTML+="<br/>";
        infoHTML+="On Array: "+this.maxHorizontalParts()+" X "+this.maxVerticalParts();
    }
    else {
        infoHTML+="On Panel: "+this.maxHorizontalParts()+" X "+this.maxVerticalParts();
    }
    infoHTML+="</div>";
    
    infoHTML+="<b>Spacing</b><br/>";
    infoHTML+="<div style='padding-left:10px' >";
    infoHTML+=this.panelSpacing.toFixed(4)+" X "+this.panelSpacing.toFixed(4);
    infoHTML+="</div>";
    
    infoHTML+="<b>Panel Borders</b><br/>";
    infoHTML+="<div style='padding-left:10px' >";
    infoHTML+="Left: "+this.PanelLeftMargin.toFixed(4);
    infoHTML+="&nbsp;&nbsp;";
    infoHTML+="Right: "+this.PanelRightMargin.toFixed(4);
    infoHTML+="<br/>";
    infoHTML+="Top: "+this.PanelTopMargin.toFixed(4);
    infoHTML+="&nbsp;&nbsp;";
    infoHTML+="Bottom: "+this.PanelBottomMargin.toFixed(4);
    infoHTML+="<br/>";
    infoHTML+="</div>";
    
    if(this.calculateArrays){
        infoHTML+="<b>Array Borders</b><br/>";
        infoHTML+="<div style='padding-left:10px' >";
        infoHTML+="Left: "+this.ArrayLeftMargin.toFixed(4);
        infoHTML+="&nbsp;&nbsp;";
        infoHTML+="Right: "+this.ArrayRightMargin.toFixed(4);
        infoHTML+="<br/>";
        infoHTML+="Top: "+this.ArrayTopMargin.toFixed(4);
        infoHTML+="&nbsp;&nbsp;";
        infoHTML+="Bottom: "+this.ArrayBottomMargin.toFixed(4);
        infoHTML+="<br/>";
        infoHTML+="</div>";
    }
    
    infoHTML+="<br/><br/>";
    
    infoBox.innerHTML=infoHTML;
    
    var label=document.createElement("label");
    label.innerHTML="Notes : ";
    infoBox.appendChild(label);
    
    infoBox.appendChild(document.createElement("br"));
    
    var textArea=document.createElement("textarea");
    textArea.value="";
    textArea.id="pcbNotes";
    textArea.style.resize="none";
    textArea.style.width="100%";
    infoBox.appendChild(textArea);
    
    infoBox.appendChild(document.createElement("br"));
    
    var label=document.createElement("label");
    label.innerHTML="Email : ";
    infoBox.appendChild(label);
    
    infoBox.appendChild(document.createElement("br"));
    
    var textInput=document.createElement("input");
    textInput.type="text";
    textInput.value="";
    textInput.id="pcbEmail";
    textInput.style.width="100%";
    infoBox.appendChild(textInput);
    
    infoBox.appendChild(document.createElement("br"));
    
    infoBox.appendChild(document.createElement("br"));
    
    var button=document.createElement("input");
    button.type="button";
    button.value="Email";
    infoBox.appendChild(button);
    
    var _self=this;
    
    button.onclick=function(){
        
        
        if(!textInput.value.match(/^[0-9a-z\-\_\.]+\@[0-9a-z\-\_\.]+\.[a-z0-9]{2,4}$/i)){
            alert("Please enter valid email!")
        }
        else {
            
            var postData="action=panelizer_email&email="+encodeURIComponent(textInput.value)+"&note="+encodeURIComponent(textArea.value);
            
            if(_self.multipleParts){
                postData += "&calculationType=3";
                for(var i=0;i<_self.maxParts.length;i++){
                    postData += "&partsWidth"+(i!=0?i+1:"")+"="+_self.partsWidth[i];
                    postData += "&partsHeight"+(i!=0?i+1:"")+"="+_self.partsHeight[i];
                }
            }
            else if(_self.calculateArrays){
                postData += "&calculationType=2";
                postData += "&partsWidth="+_self.partsWidth;
                postData += "&partsHeight="+_self.partsHeight;
                postData += "&ArrayWidth="+_self.ArrayWidth;
                postData += "&ArrayHeight="+_self.ArrayHeight;
                postData += "&ArrayLeftMargin="+_self.ArrayLeftMargin;
                postData += "&ArrayRightMargin="+_self.ArrayRightMargin;
                postData += "&ArrayTopMargin="+_self.ArrayTopMargin;
                postData += "&ArrayBottomMargin="+_self.ArrayBottomMargin;
                postData += "&arraySpacing="+_self.arraySpacing;
            }
            else {
                postData += "&partsWidth="+_self.partsWidth;
                postData += "&partsHeight="+_self.partsHeight;
            }
            
            postData += "&PanelWidth="+_self.PanelWidth;
            postData += "&PanelHeight="+_self.PanelHeight;
            postData += "&PanelLeftMargin="+_self.PanelLeftMargin;
            postData += "&PanelRightMargin="+_self.PanelRightMargin;
            postData += "&PanelTopMargin="+_self.PanelTopMargin;
            postData += "&PanelBottomMargin="+_self.PanelBottomMargin;
            postData += "&panelSpacing="+_self.panelSpacing;
            

            this.calculateArrays=false;
            this.ArrayWidth=4;
            this.ArrayHeight=4;
            this.ArrayLeftMargin=0.5;
            this.ArrayRightMargin=0.5;
            this.ArrayTopMargin=0.5;
            this.ArrayBottomMargin=0.5;
            this.arraySpacing=0.1;
            
           /* var ajax= new ajaxRequest(ajaxurl+"?t="+new Date().getTime(),postData,function(thisRequestObject, sendString){
                alert("Email successfully sent!");
                textInput.value='';
                textArea.value='';
                button.disabled=false;
            }); */
            
            jQuery.post(ajaxurl+"?t="+new Date().getTime() , postData , function(){
                alert("Email successfully sent!");
                textInput.value='';
                textArea.value='';
                button.disabled=false;
            });

            button.disabled=true;
            
            //ajax.sendPostData();
            
            
           var aweberUrl = "http://www.aweber.com/scripts/addlead.pl";
           
           var aweberPostData = "meta_web_form_id=1014513996";
           aweberPostData += "&listname=bac-panlelizer";
           aweberPostData += "&redirect=http://www.aweber.com/thankyou-coi.htm?m=text";
           aweberPostData += "&meta_adtracking=form_for_panelizer_tool_submission";
           aweberPostData += "&meta_message=1";
           aweberPostData += "&meta_required=email";
           aweberPostData += "&name=";
           aweberPostData += "&email="+encodeURIComponent(textInput.value);
           aweberPostData += "&meta_tooltip=";
           aweberPostData += "&meta_split_id=";
           
           //var aweberAjax = new ajaxRequest(aweberUrl+"?t="+new Date().getTime(),aweberPostData);
           
          // aweberAjax.sendPostData();

           jQuery.post(aweberUrl+"?t="+new Date().getTime() , aweberPostData );
        }
    }
}
// Initialization function for rendering of PCB panel
PCB.prototype.init = function(){
    this.renderPanel();
    if(this.calculateArrays) this.renderArrays(); // Render Arrays
    this.renderParts();
    this.displayInfo();
}

function ajaxRequest(theURL, sendString, callbackFunction)
{

    
    var thisRequestObject;

    thisRequestObject = initiateRequest();
    
    thisRequestObject.onreadystatechange = processRequest;
    
    function initiateRequest()
    {
        if (window.XMLHttpRequest)
            return new XMLHttpRequest();
        elseif (window.ActiveXObject)
        return new ActiveXObject("Microsoft.XMLHTTP");
    }

    function processRequest()
    {
        if (thisRequestObject.readyState == 4)
        {
            if (thisRequestObject.status == 200)
            {
                if (callbackFunction)
                    callbackFunction(thisRequestObject, sendString);
            }
            else {
                //alert("There was an error: (" + thisRequestObject.status + ") " + thisRequestObject.statusText);
            }
        }
    }

    this.sendGetData = function()
    {
        if (theURL)
        {
            thisRequestObject.open("GET", theURL, true);
            thisRequestObject.send(sendString);
        }
    }

    this.sendPostData = function()
    {
        if (theURL)
        {
            thisRequestObject.open("POST", theURL, true);
            thisRequestObject.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            thisRequestObject.send(sendString);
        }
    }
    
}
