# Fixes here should be copied to teacup-osx/style.rb
module Teacup
  # The Style class is where the precedence rules are applied.  A Style can
  # query the Stylesheet that created it to look up other styles (for
  # `extends:`) and to import other Stylesheets.  If it is handed a class (e.g.
  # `UIView`) and orientation, it will merge those in appropriately as well.
  class Style < Hash
    attr_accessor :stylename
    attr_accessor :stylesheet

    Orientations = [:portrait, :upside_up, :upside_down, :landscape, :landscape_left, :landscape_right]
    Overrides = {
      0 => [:portrait, :upside_up],
      UIInterfaceOrientationPortrait => [:portrait, :upside_up],
      UIInterfaceOrientationPortraitUpsideDown => [:portrait, :upside_down],
      UIInterfaceOrientationLandscapeLeft => [:landscape, :landscape_left],
      UIInterfaceOrientationLandscapeRight => [:landscape, :landscape_right],
    }

    # A hash of orientation => true/false.  true means the orientation is
    # supported.
    def supports
      @supports ||= {}
    end

    # returns the value - `nil` has special meaning when querying :portrait or :upside_up
    def supports? orientation_key
      supports[orientation_key]
    end

    def build(target_class=nil, rotation_orientation=nil, seen={})
      properties = Style.new
      properties.stylename = self.stylename
      properties.stylesheet = self.stylesheet

      # if we have an orientation, only apply those styles.  otherwise apply the
      # entire style, including the current orientation.
      if rotation_orientation
        # in order to preserve the "local-first" override, we need to *delete*
        # the keys in imported_stylesheets and extended_properties that are
        # present in this style - even though we don't ultimately *apply* the
        # styles
        delete_keys = self.keys
        orientation = rotation_orientation
      else
        delete_keys = []
        properties.update(self)
        orientation = UIApplication.sharedApplication.statusBarOrientation
      end

      # first, move orientation settings into properties "base" level.
      Overrides[orientation].each do |orientation_key|
        if override = self[orientation_key]
          # override is first, so it takes precedence
          if override.is_a? Hash
            Teacup::merge_defaults override, properties, properties
          end
        end
      end

      # delete all of them from `properties`
      Orientations.each do |orientation_key|
        if self[orientation_key]
          properties.supports[orientation_key] = true
        end
        properties.delete(orientation_key)
      end

      # now we can merge extends, and imported_stylesheets.  before merging,
      # these will go through the same process that we just finished on the
      # local style
      if stylesheet && stylesheet.is_a?(Teacup::Stylesheet)
        stylesheet.imported_stylesheets.reverse.each do |stylesheet|
          imported_properties = stylesheet.query(self.stylename, target_class, rotation_orientation, seen)
          delete_keys.each do |key|
            imported_properties.delete(key)
          end
          Teacup::merge_defaults! properties, imported_properties
        end

        if also_includes = self[:extends]
          also_includes = [also_includes] unless also_includes.is_a? Array

          # turn style names into Hashes by querying them on the stylesheet
          # (this does not pass `seen`, because this is a new query)
          also_includes.each do |also_include|
            extended_properties = stylesheet.query(also_include, target_class, rotation_orientation)
            delete_keys.each do |key|
              extended_properties.delete(key)
            end
            Teacup::merge_defaults! properties, extended_properties
          end
        end
        properties.delete(:extends)

        # if we know the class of the target, we can apply styles via class
        # inheritance.
        if target_class
          unless target_class.is_a?(Class)
            target_class = target_class.class
          end

          target_class.ancestors.each do |ancestor|
            extended_properties = stylesheet.query(ancestor, nil, rotation_orientation)
            Teacup::merge_defaults!(properties, extended_properties)
          end
        end
      end

      return properties
    end

  end
end
