package versiontree

class Connector {
  private tclint id_
  private tclstring canv_
  
  Connector {GridCell.cell1 GridCell.cell2} {
    set canv_ [$cell1 getCanvas]
    
    set i1 [$cell1 getItem]
    set i2 [$cell2 getItem]
    
    switch [getTopology $cell1 $cell2] {
      1 {
        set p1 [$i1 getSouth]
        set p2 [$i2 getNorth]
      }
      2 {
        set p1 [$i1 getEast]
        set p2 [$i2 getWest]
      }
      3 {
        set p1 [$i1 getEast]
        set p2 [$i2 getWest]
      }
      4 {
        set p1 [$i1 getNorthEast]
        set p2 [$i2 getSouthWest]
      }
      5 {
        set p1 [$i1 getNorth]
        set p2 [$i2 getSouth]
      }
      6 {
        set p1 [$i1 getNorthWest]
        set p2 [$i2 getSouthEast]
      }
      7 {
        set p1 [$i1 getWest]
        set p2 [$i2 getEast]
      }
      8 {
        set p1 [$i1 getSouthWest]
        set p2 [$i2 getNorthEast]
      }
    }

    set id_ [eval $canv_ create line [$p1 getPoint] [$p2 getPoint] -tags LINE -width 2]
    
    # register this with the gridmgr
    set gridmgr [$cell1 getGridMgr]
    $gridmgr mapConnector $this $id_
  }
  
  Connector {GridCell.cell1 GridCell.cell2 tclbool.arrow} {
    set canv_ [$cell1 getCanvas]
    
    set i1 [$cell1 getItem]
    set i2 [$cell2 getItem]
    set bend 27
    
    set top [getTopology $cell1 $cell2]
    switch $top {
      1 {
        set p1 [$i1 getSouthWest]
        set p2 [$i2 getNorthWest]
        set p3 [new Point [expr {[$p1 getX] - $bend}] [expr {[$p1 getY] + (([$p2 getY] - [$p1 getY])/2)}]]
      }
      2 {
        set p1 [$i1 getSouthEast]
        set p2 [$i2 getNorthWest]
        set p3 [new Point [$p1 getX] [expr {[$p1 getY] + (([$p2 getY] - [$p1 getY])/2)}]]
      }
      3 {
        set p1 [$i1 getSouthEast]
        set p2 [$i2 getSouthWest]
        set p3 [new Point [expr {[$p1 getX] + (([$p2 getX] - [$p1 getX])/2)}] [expr {[$p1 getY] + $bend}]]
      }
      4 {
        set p1 [$i1 getNorthEast]
        set p2 [$i2 getSouthWest]
        set p3 [new Point [$p1 getX] [expr {[$p2 getY] + (([$p1 getY] - [$p2 getY])/2)}]]
      }
      5 {
        set p1 [$i1 getNorthEast]
        set p2 [$i2 getSouthEast]
        set p3 [new Point [expr {[$p1 getX] + $bend}] [expr {[$p1 getY] + (([$p2 getY] - [$p1 getY])/2)}]]
      }
      6 {
        set p1 [$i1 getNorthWest]
        set p2 [$i2 getSouthEast]
        set p3 [new Point [$p1 getX] [expr {[$p2 getY] + (([$p1 getY] - [$p2 getY])/2)}]]
      }
      7 {
        set p1 [$i1 getNorthWest]
        set p2 [$i2 getNorthEast]
        set p3 [new Point [expr {[$p1 getX] + (([$p2 getX] - [$p1 getX])/2)}] [expr {[$p1 getY] - $bend}]]
      }
      8 {
        set p1 [$i1 getSouthWest]
        set p2 [$i2 getNorthEast]
        set p3 [new Point [$p1 getX] [$p2 getY]]
      }
    }
    
    if { $arrow } {
      set arrowopt "-arrow last"
    } else {
      set arrowopt ""
    }
    
    set id_ [eval $canv_ create line [$p1 getPoint] [$p3 getPoint] [$p2 getPoint] -smooth on $arrowopt -tags LINE -width 2 -splinesteps 20]

    # register this with the gridmgr
    set gridmgr [$cell1 getGridMgr]
    $gridmgr mapConnector $this $id_
  }
  
  # this returns a integer describing which of the following topologies
  # the two cells have:
  #
  # (1)    1     (2)    1    (3)  1 - 2    (4)      2
  #        |             \                         /
  #        2              2                       1
  #
  # (5)    2     (6)    2    (7)  2 - 1    (8)      1
  #        |             \                         /
  #        1              1                       2
  #

  private tclint getTopology {GridCell.cell1 GridCell.cell2} {
    set x1 [$cell1 getX]
    set x2 [$cell2 getX]
    
    set y1 [$cell1 getY]
    set y2 [$cell2 getY]
    
    if { $x1 < $x2 } {
      if { $y1 < $y2 } {
        return 2
      } elseif {$y1 == $y2} {
        return 3
      } else {
        return 4
      }
    } elseif {$x1 == $x2} {
      if { $y1 < $y2 } {
        return 1
      } elseif {$y1 == $y2} {
        throw [new Throwable "impossible topology combination, they're on top of each other"]
      } else {
        return 5
      }
    } else {
      if { $y1 < $y2 } {
        return 8
      } elseif {$y1 == $y2} {
        return 7
      } else {
        return 6
      }
    }
  }
  
  void select {} {
    $canv_ itemconfigure $id_ -fill red
  }
  
  void unselect {} {
    $canv_ itemconfigure $id_ -fill black
  }
}
