require 'ipaddr'

module Tapyrus
  module Message

    class NetworkAddr

      # unix time.
      # Nodes advertising their own IP address set this to the current time.
      # Nodes advertising IP addresses they’ve connected to set this to the last time they connected to that node.
      # Other nodes just relaying the IP address should not change the time. Nodes can use the time field to avoid relaying old addr messages.
      attr_accessor :time

      # The services the node advertised in its version message.
      attr_accessor :services

      attr_accessor :ip_addr # IPAddr

      attr_accessor :port

      attr_reader :skip_time

      def initialize(ip: '127.0.0.1', port: Tapyrus.chain_params.default_port, services: DEFAULT_SERVICE_FLAGS, time: Time.now.to_i)
        @time = time
        @ip_addr = IPAddr.new(ip)
        @port = port
        @services = services
      end

      def self.parse_from_payload(payload)
        buf = payload.is_a?(String) ? StringIO.new(payload) : payload
        has_time = buf.size > 26
        addr = new(time: nil)
        addr.time = buf.read(4).unpack('V').first if has_time
        addr.services = buf.read(8).unpack('Q').first
        addr.ip_addr = IPAddr::new_ntoh(buf.read(16))
        addr.port = buf.read(2).unpack('n').first
        addr
      end

      def self.local_addr
        addr = new
        addr.ip_addr = IPAddr.new('127.0.0.1')
        addr.port = Tapyrus.chain_params.default_port
        addr.services = DEFAULT_SERVICE_FLAGS
        addr
      end

      def ip
        ip_addr.ipv4_mapped? ? ip_addr.native : ip_addr.to_s
      end

      def to_payload(skip_time = false)
        p = ''
        p << [time].pack('V') unless skip_time
        addr = ip_addr.ipv4? ? ip_addr.ipv4_mapped : ip_addr
        p << [services].pack('Q') << addr.hton << [port].pack('n')
      end

    end

  end
end
