# frozen_string_literal: true
require_relative './connection_data'

module Hypertube
  module Utils
    class TcpConnectionData < ConnectionData
      attr_reader :hostname, :ip_address, :port

      def initialize(hostname)
        super()
        host_only, port = parse_hostname(hostname)
        @hostname = "#{host_only}:#{port}"
        @port = port
        if host_only == 'localhost'
          @ip_address = '127.0.0.1'
        else
          begin
            @ip_address = IPSocket.getaddress(host_only)
          rescue SocketError
            raise 'Unable to resolve hostname to an IP address.'
          end
        end
      end

      def connection_type
        ConnectionType::TCP
      end

      def to_s
        "tcp|#{@hostname}"
      end

      def get_address_bytes
        @ip_address.split('.').map(&:to_i)
      end

      def get_port_bytes
        [@port & 0xFF, @port >> 8]
      end

      def serialize_connection_data
        [Hypertube::Utils::ConnectionType::TCP] + get_address_bytes + get_port_bytes
      end

      private

      def parse_hostname(hostname)
        value = hostname.to_s.strip
        value = value[6..-1] if value.downcase.start_with?('tcp://')
        raise 'TCP addresses do not support route paths.' if value.include?('/')

        colon = value.rindex(':')
        raise 'TCP hostname must use host:port format.' if !colon || colon <= 0 || colon >= value.length - 1

        host_only = value[0...colon].strip
        port = Integer(value[colon + 1..-1])
        if host_only.empty? || port.negative? || port > 65_535
          raise 'TCP hostname must contain a non-empty host and port between 0 and 65535.'
        end

        [host_only, port]
      rescue ArgumentError
        raise 'TCP hostname must contain a numeric port.'
      end

    end
  end
end
