/*************************************
  File: WallObject.js
  Created by Hawkeye
  Create Date: 8.27.2002

  I am the wall are us.

  I keep two groups.  One for the wall drawings and one for the wall event catching masks.  That's going to be two headaches when I get pulled out of the database, yo!

  Okay, wait a minute, this app is going to have to "use walls" in the same way that we "use canvas" right now.  So, the wall group should be like that.  We should NOT build the wall group into this object.  Instead the wall group should be a global thing.

Right, so I will contain a) one wall drawing group, b) pointers to all the lines of my wall, c) descriptions of my fundamental line and the two fundamental lines on either side of me and d) a pointer to my line mask.

FURTHERMORE,  ALL MY SHAPES will have thier SELECT handlers redefined to select the mask as well.

============================
Modified 9/10 by Hawkeye

All four boundary lines are now drawn.
But maybe the boundary should just be a path...
============================

**************************************/

WallObject.prototype = new Shape();
WallObject.constructor = WallObject;
WallObject.superclass = Shape.prototype;

function WallObject( lineList, neighborA, neightborB, draw ){

  if ( arguments.length ){
    this.init( lineList, neighborA, neightborB, draw );
  }
}
// WallObject.prototype.grouptype = "WallObject";

WallObject.prototype.init = function( fundementalLine, neighborA, neighborB, draw ) {
  WallObject.superclass.init.call( this );
  this.line = fundementalLine;
  this.n1=neighborA;
  this.n2=neighborB;
  if ( draw ) {
    this.make();
  }
}

WallObject.prototype.make = function() {
  this.line.svgNode.setAttribute("stroke","red");

  // THE FOLLOWING CONVOLUTED CODE IS ALL TO DRAW THE ENCOMPASSING LINES AROUND THE WALLS.

  // length of fundamental line
  var p1= this.line.handles[0].point; 
  var p2= this.line.handles[1].point; 
  dx0 = p1.x - p2.x;
  dy0 = p1.y - p2.y;
  dd0 = Math.sqrt( (dy0 * dy0) + (dx0 * dx0) );
  
  // if there's no neighbor make make a mockup line to calculate from
  if (!this.n1){
    var p3 = new Point2D();
    p3.setFromPoint(p2);
    var p4 = new Point2D();
    p4.setFromPoint(p1);
  }else{
    var p3 = this.n1.handles[1].point;
    var p4 = this.n1.handles[0].point;
  }

  // length of first neighbor line
  dxn = p3.x - p4.x;
  dyn = p3.y - p4.y;
  ln1 = Math.sqrt( (dyn * dyn) + (dxn * dxn) );

  // calculate line ascention difference (that is the distance from the fundamental vertex two the drawn corner)
  var costheta = ((dx0 * dxn) + ( dy0 * dyn )) / ( dd0 * ln1 ); 
  var theta = Math.acos( costheta ); // theta is the angle between the two lines
  var theta2 = ( Math.PI - theta ) / 2;
  var H1 = (wallWidth/2) / Math.cos( theta2 );  // H1 is the "ascention difference"

  // calculate angle orientation for by finding area via crossproduct
  var XP1= (p2.x - p1.x )*(p4.y-p1.y)-(p4.x-p1.x) * (p2.y-p1.y);

  // neighbors are co-linear.
  if ( Math.abs(costheta) >= 0.99998){
    H1 = wallWidth/2;
    var m=  (p1.x - p2.x)/(p1.y - p2.y);
    dx1 = Math.sqrt( H1*H1 / (m*m + 1 ) )
    dy1 = Math.sqrt( H1*H1 - dx1*dx1);
    var signx = (p1.x-p2.x) > 0 ? 1 : (p1.x-p2.x) == 0 ? 1 : -1;
    var signy = (p1.y-p2.y) > 0 ? 1 : (p1.y-p2.y) == 0 ? 1 : -1;
    XP1 = signx * signy * -1;
    dy1 = dy1 * signy; 
    dx1 = dx1 * signx * -1;
  }else{
     // calculate 2nd line bisector endpoint (1st is p1)
    //  this.baseline = new Line( p2.x, p2.y, p4.x,p4.y, false, true);  
    D1 = ln1;
    D2 = dd0;
    var l0x = (p4.x) - (p2.x);
    var l0y = (p4.y) - (p2.y);
    var l2x = ( D2 * l0x ) / (D1 + D2);
    var l2y = ( D2 * l0y ) / (D1 + D2);
    pBx = p2.x + l2x; // 2nd bisector endpoint
    pBy = p2.y + l2y; // ""  ""  ""
    // this.bisector = new Line( p1.x, p1.y, pBx, pBy, false, true);
    // bisector length
    dBx = pBx - p1.x;
    dBy = pBy - p1.y;
    ddB = Math.sqrt( (dBx * dBx) + (dBy * dBy) );
    dx1 = (H1 * dBx) / ddB; // distance from fundemental endpoint to drawn corner.
    dy1 = (H1 * dBy) / ddB; // ""  ""  ""
  }

  // DO IT AGAIN FOR SECOND NEIGHBOR!
  // DO IT AGAIN FOR SECOND NEIGHBOR!
  // DO IT AGAIN FOR SECOND NEIGHBOR!

  // length of second neighboring line
  if (!this.n2){
    var p3 = new Point2D();
    p3.setFromPoint(p1);
    var p4 = new Point2D();
    p4.setFromPoint(p2);
  }else{
    var p3 = this.n2.handles[1].point;
    var p4 = this.n2.handles[0].point;
  }

  dxn = p4.x - p3.x;
  dyn = p4.y - p3.y;
  ln2 = Math.sqrt( (dyn * dyn) + (dxn * dxn) );

  // calculate line ascention difference
  // d0 is dimension of fundemental line.
  // dn is dimension of neighbor line
  // theta is angle between them.
  var costheta = ((dx0 * dxn * -1) + ( dy0 * dyn * -1)) / ( dd0 * ln2 );
  theta = (costheta == 1 || costheta == -1) ? Math.PI : Math.acos( costheta );
  var theta2 = ( Math.PI - theta ) / 2;
  var H2 = (wallWidth/2)/ Math.cos( theta2 );

  // if the lines are colinear there is no calculable bisector, so use a different method.
  if ( Math.abs(costheta) >= 0.99998){
    H2 = wallWidth/2;
    var m=  (p1.x - p2.x)/(p1.y - p2.y);
    var delta = p1.subtract( p2 );

    // delta orientation which direction does the line go relative to the previous angle?
    // Yes, it's ugly.  No, I don't care.
    if (delta.x > 0 && delta.y > 0) {
      var sign = " +1 ";
      var multx = (XP1 > 0) ? 1 : -1;
      var multy = (XP1 < 0) ? 1 : -1;
    } else if (delta.x < 0 && delta.y < 0) {
      var sign = " -1 ";
      var multx = (XP1 > 0) ? -1 : 1;
      var multy = (XP1 < 0) ? -1 : 1;
    } else if ( delta.x == 0 && delta.y > 0 ) {
      var sign = " +1 (00) ";
      var multx = (XP1 > 0) ? 1 : -1;
      var multy = (XP1 > 0) ? 1 : -1;
    } else if ( delta.x > 0 && delta.y == 0 ) {
      var sign = " +1 (01) ";
      var multx = (XP1 < 0) ? 1 : -1;
      var multy = (XP1 < 0) ? 1 : -1;

    } else if ( delta.x == 0 && delta.y < 0 ) {
      var sign = " -1 (00) ";
      var multx = (XP1 > 0) ? -1 : 1;
      var multy = (XP1 > 0) ? -1 : 1;
    } else if ( delta.x < 0 && delta.y == 0 ) {
      var sign = " -1 (01) ";
      var multx = (XP1 < 0) ? -1 : 1;
      var multy = (XP1 < 0) ? -1 : 1;
    } else if ( delta.x > 0 && delta.y < 0 ) {
      var sign = "-1(r0)";
      var multx = (XP1 > 0) ? -1 : 1;
      var multy = (XP1 > 0) ? -1 : 1;
    } else if ( delta.x < 0 && delta.y > 0 ) {
      var sign = "-1(r1)";
      var multx = (XP1 > 0) ? 1 : -1;
      var multy = (XP1 > 0) ? 1 : -1;
    }

    // the slope-intercepted reverse pythagorized hypoteneuse of a wrong triangle in Euclid's worst nightmare.
    dx2 = Math.sqrt( H2*H2 / (m*m + 1 ) ) * multx;
    dy2 = Math.sqrt( H2*H2 - dx2*dx2) * multy;

  } else {  // LINES ARE NOT CO-LINEAR
    // calculate angle orientation of second angle.
    var XP2= (p1.x - p2.x )*(p3.y-p2.y)-(p3.x-p2.x) * (p1.y-p2.y);
    // compare orientations of two angles to determine corner projection orientation.
    if ( ( XP2 < 0 && XP1 <=0) || (XP2 > 0 && XP1 >= 0) ){
      var reversed = true;
      H2 = H2 * -1;
    }

    // calculate 2nd bisector endpoint (1st is p2)
    //  this.baseline = new Line( p1.x, p1.y, p3.x,p3.y, false, true);  
    //  this.baseline.tempLine();
    D1 = ln2;
    D2 = dd0;
    var l0x = (p3.x) - (p1.x);
    var l0y = (p3.y) - (p1.y);
    var l2x = ( D2 * l0x ) / (D1 + D2);
    var l2y = ( D2 * l0y ) / (D1 + D2);
    
    pBx = p1.x + l2x;
    pBy = p1.y + l2y;
    //  this.bisector = new Line( p2.x, p2.y, pBx, pBy, false, true);  
    //  this.bisector.tempLine();
    
    // bisector length
    dBx = pBx -p2.x;
    dBy = pBy -p2.y;
    ddB = Math.sqrt( (dBx * dBx) + (dBy * dBy) );
    
    // project bisect line to find corner point.
    // use the ratio of the overall length to the Hypoteneuse length to find ratio of overall vectors to projected vectors.(projected vector = projected line)
    dx2 = (H2 * dBx) / ddB;
    dy2 = (H2 * dBy) / ddB;
  }

  // DRAW LINES!  FINALLY!

  var C1x = p1.x - dx1;
  var C4x = p2.x - dx2;
  var C2x = p1.x + dx1;
  var C3x = p2.x + dx2;

  var C1y = p1.y - dy1;
  var C4y = p2.y - dy2;
  var C2y = p1.y + dy1;
  var C3y = p2.y + dy2;

/*  this.border = new Polygon( true, C1x, C1y, C2x, C2y, C3x, C3y, C4x, C4y );
  this.border.setShapeStyle( "fill", "none");
  this.border.setShapeStyle( "stroke", "black");
  this.border.setShapeStyle( "stroke-width", "1");
  this.border.setShapeStyle( "stroke-linejoin", "round");
  this.border.svgNode.setAttribute( "id", "wall");
  this.border.svgNode.removeEventListener("click", this.border, false);
  this.border.svgNode.addEventListener("click", this, false); */
  
	this.initBorder( true, C1x, C1y, C2x, C2y, C3x, C3y, C4x, C4y );
	this.svgNode = this.border.svgNode;
}

WallObject.prototype.initBorder = function( boo, C1x, C1y, C2x, C2y, C3x, C3y, C4x, C4y ){
  if (arguments.length > 0){
    this.border = new Polygon( boo, C1x, C1y, C2x, C2y, C3x, C3y, C4x, C4y );
  } else {
    this.border = new Polygon( true, 1,1,1,1);
  }	
  this.border.setShapeStyle( "fill", "none");
  this.border.setShapeStyle( "stroke", "black");
  this.border.setShapeStyle( "stroke-width", "1");
  this.border.setShapeStyle( "stroke-linejoin", "round");
  this.border.svgNode.setAttribute( "id", "wall");
  this.border.svgNode.removeEventListener("click", this.border, false);
  this.border.svgNode.addEventListener("click", this, false);
}
	
WallObject.prototype.update = function(){
  this.border.update();
  this.line.update();
}

WallObject.prototype.move = function( delta ) {
  this.line.move(delta);
  this.border.move(delta);
}
WallObject.prototype.initTransform = function( from ){
  this.line.initTransform(from);
  this.border.initTransform(from);
}  
WallObject.prototype.scalePlease = function( from, percentx, percenty ){ 
  this.line.scalePlease( from, percentx, percenty );
  this.border.scalePlease( from, percentx, percenty );
}
WallObject.prototype.rotatePlease = function( from, angle ){
  this.line.rotatePlease( from, angle );
  this.border.rotatePlease( from, angle );
}
WallObject.prototype.copyconstructor = function( svgNode, wallLine ){
  this.line = wallLine;
  this.border = polygonTool.copyconstructor( svgNode );
  this.border.svgNode.setAttribute("id", "wall");
  this.border.svgNode.removeEventListener("click", this.border, false);
  this.border.svgNode.addEventListener("click", this, false);
  this.svgNode = svgNode;
}
WallObject.prototype.destructor = function(){
  this.line.destructor();
  this.border.destructor();
}
