module AIPP
  module LF

    class NavigationalAids < AIP

      include AIPP::LF::Helpers::Base

      SOURCE_TYPES = {
        'DME-ATT' => [:dme],
        'TACAN' => [:tacan],
        'VOR' => [:vor],
        'VOR-DME' => [:vor, :dme],
        'VORTAC' => [:vor, :tacan],
        'NDB' => [:ndb]
      }.freeze

      def parse
        SOURCE_TYPES.each do |source_type, (primary_type, secondary_type)|
          verbose_info("Processing #{source_type}")
          cache.navfix.css(%Q(NavFix[lk^="[LF][#{source_type} "])).each do |navfix_node|
            attributes = {
              source: source(section: 'ENR', position: navfix_node.line),
              organisation: organisation_lf,
              id: navfix_node.(:Ident),
              xy: xy_from(navfix_node.(:Geometrie))
            }
            if radionav_node = cache.radionav.at_css(%Q(RadioNav:has(NavFix[pk="#{navfix_node.attr(:pk)}"])))
              attributes.merge! send(primary_type, radionav_node)
              navigational_aid = AIXM.send(primary_type, **attributes)
              navigational_aid.timetable = timetable_from(radionav_node.(:HorCode))
              navigational_aid.remarks = {
                "location/situation" => radionav_node.(:Situation),
                "range/portée" => range_from(radionav_node)
              }.to_remarks
              add(navigational_aid)
              add(navigational_aid.send("associate_#{secondary_type}")) if secondary_type
            else
              verbose_info("Skipping incomplete #{source_type} #{attributes[:id]}")
            end
          end
        end
      end

      private

      # TODO: associate navaid to airport (requires dependency)

      def dme(radionav_node)
        {
          ghost_f: AIXM.f(radionav_node.(:Frequence).to_f, :mhz),
          z: AIXM.z(radionav_node.(:AltitudeFt).to_i, :qnh)
        }
      end
      alias_method :tacan, :dme

      def vor(radionav_node)
        {
          type: :conventional,
          north: :magnetic,
          name: radionav_node.(:Station),
          f: AIXM.f(radionav_node.(:Frequence).to_f, :mhz),
          z: AIXM.z(radionav_node.(:AltitudeFt).to_i, :qnh),
        }
      end

      def ndb(radionav_node)
        {
          type: :en_route,
          f: AIXM.f(radionav_node.(:Frequence).to_f, :khz),
          z: AIXM.z(radionav_node.(:AltitudeFt).to_i, :qnh)
        }
      end

      def range_from(radionav_node)
        [
          radionav_node.(:Portee).blank_to_nil&.concat('NM'),
          radionav_node.(:FlPorteeVert).blank_to_nil&.prepend('FL'),
          radionav_node.(:Couverture).blank_to_nil
        ].compact.join(' / ')
      end

    end
  end
end
