require "socket"

module AsyncDNS
  abstract struct RR
    property :name, :class, :type, :ttl

    def initialize(@name : String, @class : DNSClass, @type : RRType,
                   @ttl : Int32)
    end

    struct A < RR
      property :address

      def initialize(name, @address : Socket::IPAddress, ttl)
        super(name, DNSClass::IN, RRType::A, ttl)
      end
    end

    struct AAAA < RR
      property :address

      def initialize(name, @address : Socket::IPAddress, ttl)
        super(name, DNSClass::IN, RRType::AAAA, ttl)
      end
    end

    struct CNAME < RR
      property :alias

      def initialize(name, @alias : String, ttl)
        super(name, DNSClass::IN, RRType::CNAME, ttl)
      end
    end

    struct HINFO < RR
      property :cpu, :os

      def initialize(name, @cpu : String, @os : String, ttl)
        super(name, DNSClass::IN, RRType::HINFO, ttl)
      end
    end

    struct MX < RR
      property :preference, :mx

      def initialize(name, @preference : UInt16, @mx : String, ttl)
        super(name, DNSClass::IN, RRType::MX, ttl)
      end
    end

    struct NS < RR
      property :authority

      def initialize(name, @authority : String, ttl)
        super(name, DNSClass::IN, RRType::NS, ttl)
      end
    end

    struct PTR < RR
      property :domain

      def initialize(name, @domain : String, ttl)
        super(name, DNSClass::IN, RRType::PTR, ttl)
      end
    end

    struct RP < RR
      property :mailbox, :domain

      def initialize(name, @mailbox : String, @domain : String, ttl)
        super(name, DNSClass::IN, RRType::RP, ttl)
      end
    end

    struct SOA < RR
      property :primary_ns, :responsible, :serial, :refresh, :retry,
        :expire, :min_ttl

      def initialize(name, @primary_ns : String, @responsible : String,
                     @serial : UInt32, @refresh : UInt32, @retry : UInt32,
                     @expire : UInt32, @min_ttl : UInt32)
        super(name, DNSClass::IN, RRType::SOA, ttl)
      end
    end

    struct SRV < RR
      property :prio, :weight, :target, :port

      def initialize(name, @prio : UInt16, @weight : UInt16, @target : String,
                     @port : UInt16, ttl)
        super(name, DNSClass::IN, RRType::SRV, ttl)
      end
    end

    struct TXT < RR
      property :text

      def initialize(name, @text : Array(String), ttl)
        super(name, DNSClass::IN, RRType::TXT)
      end
    end
  end
end
