require 'fox'

module Fox
  
  class FX_IconItem
    def <=>(otherItem)
      text <=> otherItem.text
    end
  end
  
  class FX_ListItem
    def <=>(otherItem)
      text <=> otherItem.text
    end
  end
  
  class FX_TreeItem
    def <=>(otherItem)
      text <=> otherItem.text
    end
  end
  
  class FXPoint
  
    alias initializeXY initialize
    
    def initialize(*args)
      if args.length == 0
        initializeXY(0, 0)
      elsif args.length == 1
        if args[0].kind_of?(FXSize)
          initializeXY(args[0].w, args[0].h)
        elsif args[0].kind_of?(FXPoint)
          initializeXY(args[0].x, args[0].y)
        else
          raise TypeError, 'expected FXPoint or FXSize'
        end
      else
        initializeXY(args[0], args[1])
      end
    end
    
    def clone
      FXPoint.new(x, y)
    end 
    
    def ==(other)
      if other.kind_of?(FXPoint)
        (self.x == other.x) && (self.y == other.y)
      else
        false
      end
    end
    
    def -@
      FXPoint.new(-self.x, -self.y)
    end
    
    def +(other)
      if other.kind_of?(FXPoint)
        FXPoint.new(self.x + other.x, self.y + other.y)
      elsif other.kind_of?(FXSize)
        FXPoint.new(self.x + other.w, self.y + other.h)
      else
        raise TypeError, 'expected FXPoint or FXSize'
      end
    end
    
    def -(other)
      if other.kind_of?(FXPoint)
        FXPoint.new(self.x - other.x, self.y - other.y)
      elsif other.kind_of?(FXSize)
        FXPoint.new(self.x - other.w, self.y - other.h)
      else
        raise TypeError, 'expected FXPoint or FXSize'
      end
    end
    
    def *(other)
      FXPoint.new(other*self.x, other*self.y)
    end
    
    def /(other)
      FXPoint.new(self.x/other, self.y/other)
    end
  end
  
  class FXRectangle
  
    alias initialize4 initialize
    
    def initialize(*args)
      if args.length == 0
        initialize4(0, 0, 0, 0)
      elsif args.length == 2
        if args[0].kind_of?(FXPoint) && args[1].kind_of?(FXSize)
          p = args[0]
          s = args[1]
          initialize4(p.x, p.y, s.w, s.h)
        else
          topleft = args[0]
          bottomright = args[1]
          initialize4(topleft.x, topleft.y, bottomright.x-topleft.x+1, bottomright.y-topleft.y+1)
        end
      else
        xx, yy, ww, hh = args[0], args[1], args[2], args[3]
        initialize4(xx, yy, ww, hh)
      end
    end

    def clone
      FXRectangle.new(x, y, w, h)
    end 

    def ==(other)
      if other.kind_of?(FXRectangle)
        (self.x == other.x) && (self.y == other.y) && (self.w == other.w) && (self.h == other.h)
      else
        false
      end
    end
    
    # Point in rectangle?
    def contains(*args)
      if args.length == 1
        if args[0].kind_of?(FXPoint)
          contains(args[0].x, args[0].y)
        elsif args[0].kind_of?(FXRectangle)
          r = args[0]
          x <= r.x && y <= r.y && r.x+r.w<=x+w && r.y+r.h<=y+h
        else
          raise TypeError, 'expected FXPoint or FXRectangle'
        end
      elsif args.length == 2
        xx, yy = args[0], args[1]
        x <= xx && y <= yy && xx < x+w && yy < y+h
      end
    end
    
    # Rectangles overlap?
    def overlaps?(other)
      if other.kind_of?(FXRectangle)
        self.x<other.x+other.w && self.y<other.y+other.h && other.x<self.x+self.w && other.y<self.y+self.h
      else
        raise TypeError, 'expected another FXRectangle'
      end
    end
    
    # Return moved rectangle
    def move(dx, dy)
      self.x = self.x + dx
      self.y = self.y + dy
      self
    end
    
    # Grow by amount
    def grow(*args)
      if args.length == 1
        margin = args[0]
        grow(margin, margin, margin, margin)
      elsif args.length == 2
        hormargin = args[0]
        vermargin = args[1]
        grow(hormargin, hormargin, vermargin, vermargin)
      else
        leftmargin = args[0]
        rightmargin = args[1]
        topmargin = args[2]
        bottommargin = args[3]
        self.x = self.x - leftmargin
        self.y = self.y - topmargin
        self.w = self.w + (leftmargin + rightmargin)
        self.h = self.h + (topmargin + bottommargin)
      end
      self
    end
    
    # Shrink by amount
    def shrink(*args)
      if args.length == 1
        margin = args[0]
        shrink(margin, margin, margin, margin)
      elsif args.length == 2
        hormargin = args[0]
        vermargin = args[1]
        shrink(hormargin, hormargin, vermargin, vermargin)
      else
        leftmargin = args[0]
        rightmargin = args[1]
        topmargin = args[2]
        bottommargin = args[3]
        self.x = self.x + leftmargin
        self.y = self.y + topmargin
        self.w = self.w - (leftmargin + rightmargin)
        self.h = self.h - (topmargin + bottommargin)
      end
      self
    end
    
    # Corners
    def tl
      FXPoint.new(self.x, self.y)
    end
    
    def tr
      FXPoint.new(self.x+self.w-1, self.y)
    end
    
    def bl
      FXPoint.new(self.x, self.y+self.h-1)
    end
    
    def br
      FXPoint.new(self.x+self.w-1, self.y+self.h-1)
    end
    
    # Union with rectangle
    def +(other)
      if other.kind_of?(FXRectangle)
        xx = [other.x, self.x].min
        ww = [other.x+other.w, self.x+self.w].max - xx
        yy = [other.y, self.y].min
        hh = [other.y+other.h, self.y+self.h].max - yy
        FXRectangle.new(xx, yy, ww, hh)
      else
        raise TypeError, 'expected FXRectangle'
      end
    end
    
    # Intersection with rectangle
    def *(other)
      if other.kind_of?(FXRectangle)
        xx = [other.x, self.x].max
        ww = [other.x+other.w, self.x+self.w].min - xx
        yy = [other.y, self.y].max
        hh = [other.y+other.h, self.y+self.h].min - yy
        FXRectangle.new(xx, yy, ww, hh)
      else
        raise TypeError, 'expected FXRectangle'
      end
    end
  end
  
  class FXSize
  
    alias initializeWH initialize
    
    def initialize(*args)
      if args.length == 0
        initializeWH(0, 0)
      elsif args.length == 1
        if args[0].kind_of?(FXSize)
          initializeWH(args[0].w, args[0].h)
        else
          raise TypeError, 'expected FXSize'
        end
      else
        initializeWH(args[0], args[1])
      end
    end
    
    def clone
      FXSize.new(w, h)
    end 
    
    def ==(other)
      if other.kind_of?(FXSize)
        (self.w == other.w) && (self.h == other.h)
      else
        false
      end
    end
    
    def -@
      FXSize.new(-self.w, -self.h)
    end
    
    def +(other)
      if other.kind_of?(FXSize)
        FXSize.new(self.w + other.w, self.h + other.h)
      else
        raise TypeError, 'expected FXSize'
      end
    end
    
    def -(other)
      if other.kind_of?(FXSize)
        FXSize.new(self.w - other.w, self.h - other.h)
      else
        raise TypeError, 'expected FXSize'
      end
    end
    
    def *(other)
      FXSize.new(other*self.w, other*self.h)
    end
    
    def /(other)
      FXSize.new(self.w/other, self.h/other)
    end
  end
end
