CoralMUD-0.15/
CoralMUD-0.15/core/
CoralMUD-0.15/data/
CoralMUD-0.15/data/areas/
CoralMUD-0.15/data/help/
CoralMUD-0.15/data/players/
CoralMUD-0.15/lib/automap/
CoralMUD-0.15/lib/items/
class String
  def derive_tag
    arr = []
    self.split("::").each do |part|
      arr.unshift part.split(".")
    end
#    self.split("::").reverse
    arr.compact
  end
end

class Array
  def revert_tag
    return self[0].join '.'
  end
end

class Tag 
  @@classes_with_tags = {}
  def to_yaml_properties
    ['@vtag']
  end

  # tag_str is in the format of a.stinky.cat
  def initialize tag_str, obj, namespace=nil
    Tag.clear_tag obj
    @vtag = tag_str.derive_tag
    obj.namespace = namespace
    @@classes_with_tags[[namespace, @vtag.revert_tag]] =  obj # The specific class and the specific tag are the key to looking up the obj  
  end


  # intended to be a fast lookup if you have all the keys.
  def self.get_index namespace, tag
    @@classes_with_tags[[namespace, tag]]
  end

  # search for all objects of a specific type.
  def self.search_class typeof
    @@classes_with_tags.each_pair do |keys, obj|
      yield obj if obj.is_a? typeof
    end
  end

  # search for all objects part of a specific namespace.
  def self.search_namespace namespace=nil
    @@classes_with_tags.each_pair do |keys, obj|
      yield obj if keys[0] == namespace
    end
  end

  # returns the full tag representing an object.  Builds it somewhat dynamically and relies heavily on uncorrupted data.
  def self.full_tag obj
    arr = []
    while obj
      arr.unshift obj.vtag.to_s
      obj = obj.namespace #
    end
    arr.join "::" # should build something like  a.continent::a.area 
  end

  def reassociate obj, namespace=nil
    Tag.clear_tag obj
    obj.namespace = namespace
    if @@classes_with_tags[[namespace, @vtag.revert_tag]]
      obj.assign_tag Tag.gen_generic_tag(obj), namespace
    end
    @@classes_with_tags[[namespace, @vtag.revert_tag]] =  obj # The specific class and the specific tag are the key to looking up the obj  
  end

  # generates a tag like:   alpha.fife or foxtrot.niner
  def self.gen_generic_tag obj
    alpha_data = %w{ alpha bravo charlie delta echo foxtrot golf hotel india juliet kilo lima mike november oscar papa quebec romeo sierra tango uniform victor whiskey xray yankee zulu }
    num_data = %w{ wun too tree fower fife siks seven ait niner zeero }
    alpha_range = ('a'..'zzz')
    numeric_range= (1..100)

    alpha_data.each do |alpha|
      numeric_range.each do |numeric|
        tag_str = "#{obj.class.to_s.downcase}.#{alpha}.#{numeric}"
        if @@classes_with_tags[[obj.namespace, tag_str]] == nil
          return tag_str
        end
      end
    end
  end

  def to_s
    @vtag.revert_tag
  end

  # compare this tag to either a string
  def ==(val)
    a1 = val
    a2 = @vtag[0].dup
    a1.sort!
    a2.sort!

    # for each word in a1 make sure *any* word minimally matches in a2
    a1.each do |word|
      i = 0
      found = false
      loop do
        return false if !a2[i]
        if a2[i].start_with?(word)  # if this is a match we need to make sure that array position id deleted.  It can't be used again to match
          found = true
          a2.delete_at(i) # delete this position
          break
        end
        i += 1
      end
      return false if !found # if this match didn't pass return false.
    end
    return true
  end

  def self.clear_tag obj
    @@classes_with_tags.delete_if do |k, v| 
      v == obj
    end
  end

  def self.find_any_obj tag_str
    found = []
    arg_arr = tag_str.derive_tag if tag_str.is_a?(String) # derive the tag array
#    pp arg_arr
    # search the hash for this exact key exists
    @@classes_with_tags.each_pair do |keys, obj|
      if obj.vtag == arg_arr[0]
        # ["obj"], ["area"], ["world"]
        # Match further only if arg_arr has additional namespaces.
        if arg_arr.count > 1 
          # Also, this obj is not a match unless it actually supports more name spaces.
          next if !obj.namespace 

          temp = arg_arr.dup # dup it so we can shift from the top.
          temp.shift # remove the one we already examined.   Now we only have name spaces.

          err = false
          next_o = obj.namespace # next_o is the obj's namespace.
          while !temp.empty? do
            if !next_o
              err = true
              break
            end
            t_el = temp.shift
            if !(next_o.vtag == t_el) # match it with the obj's vtag.  If it's a fail then look up the tree.
              err = true
              while (next_o = next_o.namespace) != nil
                if next_o.vtag == t_el
                  err = false
                  break 
                end 
              end
              break if err == true
            end
            next_o = next_o.namespace
          end

          next if err
        end
        found << obj
      end
    end
    return nil if found.empty?
    found # returns all found objects and their namespace. 
  end

end