require 'PushRadar/version'
require 'PushRadar/Utils'
require 'ipaddr'

module PushRadar

  # Specifies the target audience of a PushRadar notification
  class Targeting

    # ------------------------------
    # Initialization & configuration
    # ------------------------------

    # Creates a new notification targeting object
    def initialize

      # Initialize variables
      @target_user_ids = []
      @target_actions = []
      @target_not_actions = []
      @target_browsers = []
      @target_continents = []
      @target_countries = []
      @target_ips = []

    end

    # ------------------------------
    # Browser targeting
    # ------------------------------

    # Adds a browser to the list of target browsers
    def target_browser(browser)

      # Trim the browser and convert it to lowercase
      browser.strip!
      browser = browser.downcase

      # Validate the browser for being one of the supported types
      unless %w(chrome ie edge safari opera firefox).include? browser
        raise "The browser must be one of the following: 'chrome', 'ie', 'edge', 'safari', 'opera', 'firefox'."
      end

      # Add the browser to the list of target browser
      unless @target_browsers.include? browser
        @target_browsers.push browser
      end

    end

    # ------------------------------
    # Country targeting
    # ------------------------------

    # Adds a country to the list of target countries
    def target_country(country_code)

      # Trim the country code and convert it to uppercase
      country_code.strip!
      country_code = country_code.upcase

      # Ensure that the country code is not empty
      if country_code == ''
        raise 'The country code provided cannot be empty.'
      end

      # Validate the country code
      unless Utils.get_countries.keys.include? country_code.to_sym
        raise 'The country code provided must be a valid two-letter (ISO 3166-1 alpha-2) code.'
      end

      # Add the country to the list
      unless @target_countries.include? country_code
        @target_countries.push country_code
      end

    end

    # ------------------------------
    # Continent targeting
    # ------------------------------

    # Targets a continent by its continent code
    def target_continent(continent_code)

      # Target the countries located in this continent
      Utils.get_countries_from_continent(continent_code).each {|country|
        target_country country
      }

      # Add the continent code to the list
      unless @target_continents.include? continent_code
        @target_continents.push continent_code
      end

    end

    # ------------------------------
    # IP address targeting
    # ------------------------------

    # Targets the notification to clients with the given IP address
    def target_ip(ip_address)

      # Trim the IP address
      ip_address.strip!

      # Make sure that the IP address is not empty
      if ip_address == ''
        raise 'The IP address provided cannot be empty.'
      end

      # Check for wildcard IPs
      if ip_address.include? '*'
        raise 'Wildcard IP address targeting is not supported.'
      end

      # Validate the IP address
      unless Utils.is_valid_ip ip_address
        raise 'The IP address provided must be a valid IPv4 or IPv6 address.'
      end

      # Add the IP address to the list
      unless @target_ips.include? ip_address
        @target_ips.push ip_address
      end

    end

    # ------------------------------
    # Action targeting
    # ------------------------------

    # Targets the notification to clients who have taken the given action
    def target_action(action_identifier)

      # Trim the action identifier
      action_identifier.strip!

      # Make sure the action identifier is not empty
      if action_identifier == ''
        raise 'The action identifier cannot be empty'
      end

      # Make sure that the action is not in the target "not" actions list
      if @target_not_actions.include? action_identifier
        raise "Action '" + action_identifier + "' is already in the 'not' actions list."
      end

      # Add the action to the list
      unless @target_actions.include? action_identifier
        @target_actions.push action_identifier
      end

    end

    # Targets the notification to clients who have not taken the given action
    def target_not_action(action_identifier)

      # Trim the action identifier
      action_identifier.strip!

      # Make sure the action identifier is not empty
      if action_identifier == ''
        raise 'The action identifier cannot be empty'
      end

      # Make sure that the action is not in the target actions list
      if @target_actions.include? action_identifier
        raise "Action '" + action_identifier + "' is already in the actions list."
      end

      # Add the action to the list
      unless @target_not_actions.include? action_identifier
        @target_not_actions.push action_identifier
      end

    end

    # ------------------------------
    # User targeting
    # ------------------------------

    # Targets the notification to a specific user (identifier by their user ID)
    def target_user(user_id)

      # Make sure that the user ID is not empty
      if user_id == nil
        raise 'The user ID cannot be nil.'
      end

      # Add the user ID to the list
      unless @target_user_ids.include? user_id
        @target_user_ids.push user_id
      end

    end

  end

end