class CleanHash
  def self.pollute!
    ::Hash.class_eval do
      # merge but to not overwrite keys
      def deep_merge hash
        klass = ::CleanHash::DeepMerge
        klass[deep_clone].deep_merge klass[hash]
      end

      # true clone of the hash with 0 references to the old one
      def deep_clone
        Marshal.load(Marshal.dump(self))
      end

      def to_ch mode=nil
        if mode.is_a?(Array)
          for key in keys
            raise ArgumentError, 'CleanHash key "%s" not allowed' % key unless mode.include?(key)
          end

          for key in mode
            self[key] = nil unless key?(key)
          end

          ::CleanHash.new self, :strict
        else
          supported = %i{safe mutex strict}
          raise ArgumentError, 'Unsupported type "%s", supported: %s' % [mode, supported] if mode && !supported.include?(mode)

          if mode == :mutex
            ::CleanHash::MutexHash.new self
          else
            ::CleanHash.new self, mode
          end
        end
      end
    end

    ::Array.class_eval do
      # coverts keys to empty hash methods and returns read_only hash
      def to_ch strict=false
        hash = inject({}) { |h, key| h[key] = nil; h }
        ::CleanHash.new hash, :strict
      end
    end
  end
end