require "wikipedia"
require "json"

module PPTAccurate
  module Wikipedia
    module Client

      # Return the links that were found by the specified query.
      #
      # @param [String] query the query
      # @param [String] limit the limit, default is 500
      # @return [Array] the links
      def self.find_links(query, limit = 500)
        query_term = self.build_query(query)
        page = ::Wikipedia.find(query_term, prop: "links", pllimit: limit, redirects: true)
        self.extract_links(page)
      end

      protected

      # Build the query term with all word combiatnions from the specified query.
      #
      # @param [String] query the query
      # @return [String] the query term
      def self.build_query(query)
        combinations = self.build_combination(query.downcase)

        # Only 50 querys are allowed for one API request.
        combinations = combinations.slice(0, 50)

        combinations.join("|")
      end

      # Build all word combinations from the specified query.
      #
      # @param [String] query the query
      # @return [Array] the combinations
      def self.build_combination(query)
        words = query.split(" ")

        m = words.length
        combinations = (1..2**m).map do |n|
          (0..m).select { |i| n[i] == 1}.map do |i|
            words[i]
          end
        end.reverse
        combinations = combinations.map { |e| e.join(" ") }
        combinations.reject(&:empty?)
      end

      # Extract the links that have the namespace 0.
      #
      # @param [Wikipedia::Page] page the page
      def self.extract_links(page)
        links = Set.new

        data = JSON.load(page.json)
        pages = data['query']['pages'].values

        pages.each do |p|
          if p.has_key?('links')
            p['links'].each do |link|
              links << link
            end
          end
        end

        links = links.select {|link| link['ns'].eql?(0) }
        links.map {|link| link['title'] }
      end
    end
  end
end
