# frozen_string_literal: true

module Hypertube
  module Utils
    class ConnectionData
      THREAD_LOCAL_HEADERS_KEY = :hypertube_connection_data_thread_local_headers

      def initialize
        @headers = {}
      end

      def get_headers
        combined = @headers.dup
        thread_local_headers.each do |key, value|
          combined[key] = value
        end
        combined
      end

      alias headers get_headers

      def set_headers(headers)
        @headers = normalize_headers(headers)
      end

      def set_thread_local_headers(headers)
        Thread.current[THREAD_LOCAL_HEADERS_KEY] = normalize_headers(headers)
      end

      def get_thread_local_headers
        (Thread.current[THREAD_LOCAL_HEADERS_KEY] || {}).dup
      end

      def to_canonical_key
        key = to_s
        return key if get_headers.empty?

        "#{key}|h:#{serialize_headers_for_key}"
      end

      private

      def thread_local_headers
        Thread.current[THREAD_LOCAL_HEADERS_KEY] || {}
      end

      def normalize_headers(headers)
        return {} if headers.nil?

        headers.each_with_object({}) do |(key, value), normalized|
          normalized[key.to_s.strip.downcase] = value.to_s.strip
        end
      end

      def serialize_headers_for_key
        merged_headers = get_headers
        return '' if merged_headers.empty?

        merged_headers
          .sort_by { |key, _| key.to_s }
          .map { |key, value| "#{key}=#{value}" }
          .join(';')
      end
    end
  end
end
