module Motion ; module Xray
  # Copied from the gem of the same name, but I didn't want the dependency
  class XrayTypewriterView < UIView
    attr_accessor :scroll_view
    attr_accessor :background_view

    attr_accessor :vertical_spacing, :horizontal_spacing
    attr_accessor :top_margin, :bottom_margin
    attr_accessor :left_margin, :right_margin

    attr_accessor :centered
    attr_accessor :min_width, :min_height

    def initWithFrame(frame)
      super.tap do
        self.spacing = 0
        self.margin = 0
        self.centered = false
        self.min_width = nil
        self.min_height = nil
        self.contentMode = :bottom.uicontentmode

        @row = []
      end
    end

    def shrink
      self.frame = self.frame.height(0)
    end

    def expand
      self.frame = self.frame.height(self.subviews[0].frame.height)
    end

    def spacing=(spacing)
      if spacing.is_a? Array
        case spacing.length
        when 1
          self.spacing = spacing[0]
        when 2
          @horizontal_spacing = spacing[0]
          @vertical_spacing = spacing[1]
        end
      else
        @horizontal_spacing = @vertical_spacing = spacing
      end
    end

    def margin=(margins)
      margins = [margins] unless margins.is_a? Enumerable

      case margins.length
      when 1
        @top_margin = @bottom_margin = @left_margin = @right_margin = margins[0]
      when 2
        @top_margin = margins[0]
        @bottom_margin = margins[0]
        @left_margin = margins[1]
        @right_margin = margins[1]
      when 3
        @top_margin = margins[0]
        @bottom_margin = margins[0]
        @right_margin = margins[1]
        @left_margin = margins[2]
      when 4
        @top_margin = margins[0]
        @right_margin = margins[1]
        @bottom_margin = margins[2]
        @left_margin = margins[3]
      else
        raise "Too many arguments (#{margins.length}) sent to MarginView#margin"
      end
    end

    ##|  DEFAULTS
    def vertical_spacing
      @vertical_spacing ||= 0
      @vertical_spacing
    end
    def horizontal_spacing
      @horizontal_spacing ||= 0
      @horizontal_spacing
    end
    def top_margin
      @top_margin ||= 0
      @top_margin
    end
    def bottom_margin
      @bottom_margin ||= 0
      @bottom_margin
    end
    def left_margin
      @left_margin ||= 0
      @left_margin
    end
    def right_margin
      @right_margin ||= 0
      @right_margin
    end

    ##|
    ##|  START AT 0, 0, AND START FLOATING
    ##|
    def layoutSubviews
      super
      # super
      # the max_height of *all* the rows so far (not just the current row)
      @max_height = top_margin
      clear

      # when a row would be longer than this, it is wrapped to the next row.
      @max_x = self.frame.size.width - right_margin

      self.subviews.each do |view|
        unless view == @background_view
          view.setNeedsLayout
          view.layoutIfNeeded
          add_next(view)
        end
      end
      clear(true)  # don't add vertical spacing

      self.frame = [self.frame.origin, [self.frame.size.width, @y + bottom_margin]]
      if scroll_view
        scroll_view.scrollEnabled = (@y > scroll_view.frame.size.height)
        scroll_view.contentSize = self.frame.size
      end
      if background_view
        background_view.frame = self.bounds
      end
    end

    def setNeedsLayout
      super
    end

    def background_view=(view)
      @background_view.removeFromSuperview if @background_view && @background_view.superview == self
      view.frame = self.bounds
      self.insertSubview(view, atIndex:0)
      @background_view = view
    end

    private
    def clear(is_last_row=false)
      @x = left_margin
      @y = @max_height
      # only add the horizontal_spacing after at least one row has been written
      if @y > top_margin && ! is_last_row
        @y += vertical_spacing
      end

      if self.centered
        row_width = left_margin
        row_height = min_height || 0
        @row.each do |view|
          if row_width > 0
            row_width += horizontal_spacing
          end
          row_height = view.frame.size.height if view.frame.size.height > row_height
          row_width += view.frame.size.width
        end
        row_width += right_margin
        row_width = min_width if min_width and row_width < min_width
        x = ((self.frame.size.width - row_width) / 2).round

        @row.each do |view|
          frame = view.frame

          y = ((row_height - frame.size.height) / 2).round

          if x > 0 or y > 0
            frame.origin.x += x
            frame.origin.y += y
            view.frame = frame
          end
        end
      end
      @row = []
    end

    def add_next(subview)
      # this frame will get modified and reassigned
      subview_frame = subview.frame

      # move to the next new row?
      width = subview_frame.size.width
      if self.min_width and width < self.min_width
        width = self.min_width
      end

      next_x = @x + width
      # too big?
      if next_x > @max_x
        clear
        next_x = @x + width
      end

      # new max_height?
      height = subview_frame.size.height
      if self.min_height and height < self.min_height
        height = self.min_height
      end
      next_y = @y + height
      @max_height = next_y if next_y > @max_height

      subview_frame.origin.x = @x
      subview_frame.origin.y = @y
      @x = next_x + horizontal_spacing

      subview.frame = subview_frame
      @row.push subview
    end

  end

end end
