<?php

/**
 * Collect all the parameters ( language, key, region )
 * we need before making a request to the Google Maps API.
 *
 * @since 1.0.0
 * @param  string  $api_key_type   The type of API key we need to include ( server_key or browser_key ).
 * @param  boolean $geocode_params
 * @return string  $api_params     The API parameters.
 */
function wpsl_get_gmap_api_params( $api_key_type, $geocode_params = false ) {

    global $wpsl, $wpsl_settings;

    $api_params = '';
    $param_keys = array( 'language', 'region', 'key' );

    /*
     * The geocode params are included after the address so we need to
     * use a '&' as the first char, but when the maps script is included on
     * the front-end it does need to start with a '?'.
     */
    $first_sep = ( $geocode_params ) ? '&' : '?';

    foreach ( $param_keys as $param_key ) {
        $option_key = ( $param_key == 'key' ) ? $api_key_type : $param_key;

        /*
         * Get the current language code if WPML or qTranslate-X is active.
         * Otherwise get the param value from the settings var.
         */
        if ( $option_key == 'language' && ( $wpsl->i18n->wpml_exists() || $wpsl->i18n->qtrans_exists() ) ) {
            $param_val = $wpsl->i18n->check_multilingual_code();
        } else {
            $param_val = $wpsl_settings['api_' . $option_key];
        }

        if ( !empty( $param_val ) ) {
            $api_params .= $param_key . '=' . $param_val . '&';
        }
    }

    if ( $api_params ) {
        $api_params = $first_sep . rtrim( $api_params, '&' );
    }

    // Do we need to include the autocomplete library?
    if ( ( $wpsl_settings['autocomplete'] && $api_key_type == 'browser_key' ) || is_admin() ) {
        $api_params .= '&libraries=places';
    }

    if ( $api_key_type == 'browser_key' ) {
        $api_version = apply_filters( 'wpsl_gmap_api_version', 'quarterly' );
        $api_params .= '&v=' . $api_version;
    }

    return apply_filters( 'wpsl_gmap_api_params', $api_params );
}

/**
 * Get the default plugin settings.
 *
 * @since 1.0.0
 * @return array $default_settings The default settings
 */
function wpsl_get_default_settings() {

    $default_settings = array(
        'api_browser_key'           => '',
        'api_server_key'            => '',
        'api_language'              => 'en',
        'api_region'                => '',
        'api_geocode_component'     => 0,
        'distance_unit'             => 'km',
        'max_results'               => '[25],50,75,100',
        'search_radius'             => '10,25,[50],100,200,500',
        'force_postalcode'          => 0,
        'marker_effect'             => 'bounce',
        'address_format'            => 'city_state_zip',
        'hide_distance'             => 0,
        'hide_country'              => 0,
        'show_contact_details'      => 0,
        'clickable_contact_details' => 0,
        'auto_locate'               => 1,
        'autocomplete'              => 0,
        'autoload'                  => 1,
        'autoload_limit'            => 50,
        'run_fitbounds'             => 1,
        'zoom_level'                => 3,
        'auto_zoom_level'           => 15,
        'start_name'                => '',
        'start_latlng'              => '',
        'height'                    => 350,
        'map_type'                  => 'roadmap',
        'map_style'                 => '',
        'type_control'              => 0,
        'streetview'                => 0,
        'results_dropdown'          => 1,
        'radius_dropdown'           => 1,
        'category_filter'           => 0,
        'category_filter_type'      => 'dropdown',
        'infowindow_width'          => 225,
        'search_width'              => 179,
        'label_width'               => 95,
        'control_position'          => 'left',
        'scrollwheel'               => 1,
        'marker_clusters'           => 0,
        'cluster_zoom'              => 0,
        'cluster_size'              => 0,
        'new_window'                => 0,
        'reset_map'                 => 0,
        'template_id'               => 'default',
        'listing_below_no_scroll'   => 0,
        'direction_redirect'        => 0,
        'more_info'                 => 0,
        'store_url'                 => 0,
        'phone_url'                 => 0,
        'marker_streetview'         => 0,
        'marker_zoom_to'            => 0,
        'more_info_location'        => 'info window',
        'mouse_focus'               => 0,
        'start_marker'              => 'red.png',
        'store_marker'              => 'blue.png',
        'editor_country'            => '',
        'editor_hours'              => wpsl_default_opening_hours(),
        'editor_hour_input'         => 'dropdown',
        'editor_hour_format'        => 12,
        'editor_map_type'           => 'roadmap',
        'hide_hours'                => 0,
        'permalinks'                => 0,
        'permalink_remove_front'    => 0,
        'permalink_slug'            => __( 'stores', 'wpsl' ),
        'category_slug'             => __( 'store-category', 'wpsl' ),
        'infowindow_style'          => 'default',
        'show_credits'              => 0,
        'debug'                     => 0,
        'deregister_gmaps'          => 0,
        'delay_loading'             => 0,
        'start_label'               => __( 'Start location', 'wpsl' ),
        'search_label'              => __( 'Your location', 'wpsl' ),
        'search_btn_label'          => __( 'Search', 'wpsl' ),
        'preloader_label'           => __( 'Searching...', 'wpsl' ),
        'radius_label'              => __( 'Search radius', 'wpsl' ),
        'no_results_label'          => __( 'No results found', 'wpsl' ),
        'results_label'             => __( 'Results', 'wpsl' ),
        'more_label'                => __( 'More info', 'wpsl' ),
        'directions_label'          => __( 'Directions', 'wpsl' ),
        'no_directions_label'       => __( 'No route could be found between the origin and destination', 'wpsl' ),
        'back_label'                => __( 'Back', 'wpsl' ),
        'street_view_label'         => __( 'Street view', 'wpsl' ),
        'zoom_here_label'           => __( 'Zoom here', 'wpsl' ),
        'error_label'               => __( 'Something went wrong, please try again!', 'wpsl' ),
        'limit_label'               => __( 'API usage limit reached', 'wpsl' ),
        'phone_label'               => __( 'Phone', 'wpsl' ),
        'fax_label'                 => __( 'Fax', 'wpsl' ),
        'email_label'               => __( 'Email', 'wpsl' ),
        'url_label'                 => __( 'Url', 'wpsl' ),
        'hours_label'               => __( 'Hours', 'wpsl' ),
        'category_label'            => __( 'Category filter', 'wpsl' ),
        'category_default_label'    => __( 'Any', 'wpsl' )
    );

    return $default_settings;
}

/**
 * Get the current plugin settings.
 *
 * @since 1.0.0
 * @return array $setting The current plugin settings
 */
function wpsl_get_settings() {

    $settings = get_option( 'wpsl_settings' );

    if ( !$settings ) {
        update_option( 'wpsl_settings', wpsl_get_default_settings() );
        $settings = wpsl_get_default_settings();
    }

    return $settings;
}

/**
 * Get a single value from the default settings.
 *
 * @since 1.0.0
 * @param  string $setting               The value that should be restored
 * @return string $wpsl_default_settings The default setting value
 */
function wpsl_get_default_setting( $setting ) {

    global $wpsl_default_settings;

    return $wpsl_default_settings[$setting];
}

/**
 * Set the default plugin settings.
 *
 * @since 1.0.0
 * @return void
 */
function wpsl_set_default_settings() {

    $settings = get_option( 'wpsl_settings' );

    if ( !$settings ) {
        update_option( 'wpsl_settings', wpsl_get_default_settings() );
    }
}

/**
 * Return a list of the store templates.
 *
 * @since 1.2.20
 * @return array $templates The list of default store templates
 */
function wpsl_get_templates() {

    $templates = array(
        array(
            'id'   => 'default',
            'name' => __( 'Default', 'wpsl' ),
            'path' => WPSL_PLUGIN_DIR . 'frontend/templates/default.php'
        ),
        array(
            'id'   => 'below_map',
            'name' => __( 'Show the store list below the map', 'wpsl' ),
            'path' => WPSL_PLUGIN_DIR . 'frontend/templates/store-listings-below.php'
        )
    );

    return apply_filters( 'wpsl_templates', $templates );
}

/**
 * Return the days of the week.
 *
 * @since 2.0.0
 * @return array $weekdays The days of the week
 */
function wpsl_get_weekdays() {

   $weekdays = array(
       'monday'    => __( 'Monday', 'wpsl' ),
       'tuesday'   => __( 'Tuesday', 'wpsl' ),
       'wednesday' => __( 'Wednesday', 'wpsl' ),
       'thursday'  => __( 'Thursday', 'wpsl' ),
       'friday'    => __( 'Friday', 'wpsl' ),
       'saturday'  => __( 'Saturday', 'wpsl' ),
       'sunday'    => __( 'Sunday' , 'wpsl' )
   );

   return $weekdays;
}

/**
 * Get the default opening hours.
 *
 * @since 2.0.0
 * @return array $opening_hours The default opening hours
 */
function wpsl_default_opening_hours() {

   $current_version = get_option( 'wpsl_version' );

   $opening_hours = array(
       'dropdown' => array(
           'monday'    => array( '9:00 AM,5:00 PM' ),
           'tuesday'   => array( '9:00 AM,5:00 PM' ),
           'wednesday' => array( '9:00 AM,5:00 PM' ),
           'thursday'  => array( '9:00 AM,5:00 PM' ),
           'friday'    => array( '9:00 AM,5:00 PM' ),
           'saturday'  => '',
           'sunday'    => ''
        )
    );

   /* Only add the textarea defaults for users that upgraded from 1.x */
   if ( version_compare( $current_version, '2.0', '<' ) ) {
       $opening_hours['textarea'] = sprintf( __( 'Mon %sTue %sWed %sThu %sFri %sSat Closed %sSun Closed', 'wpsl' ), '9:00 AM - 5:00 PM' . "\n", '9:00 AM - 5:00 PM' . "\n", '9:00 AM - 5:00 PM' . "\n", '9:00 AM - 5:00 PM' . "\n", '9:00 AM - 5:00 PM' . "\n", "\n" ); //cleaner way without repeating it 5 times??
   }

   return $opening_hours;
}

/**
 * Get the available map types.
 *
 * @since 2.0.0
 * @return array $map_types The available map types
 */
function wpsl_get_map_types() {

    $map_types = array(
        'roadmap'   => __( 'Roadmap', 'wpsl' ),
        'satellite' => __( 'Satellite', 'wpsl' ),
        'hybrid'    => __( 'Hybrid', 'wpsl' ),
        'terrain'   => __( 'Terrain', 'wpsl' )
    );

    return $map_types;
}

/**
 * Get the address formats.
 *
 * @since 2.0.0
 * @return array $address_formats The address formats
 */
function wpsl_get_address_formats() {

    $address_formats = array(
        'city_state_zip'       => __( '(city) (state) (zip code)', 'wpsl' ),
        'city_comma_state_zip' => __( '(city), (state) (zip code)', 'wpsl' ),
        'city_zip'             => __( '(city) (zip code)', 'wpsl' ),
        'city_comma_zip'       => __( '(city), (zip code)', 'wpsl' ),
        'zip_city_state'       => __( '(zip code) (city) (state)', 'wpsl' ),
        'zip_city'             => __( '(zip code) (city)', 'wpsl' )
    );

    return apply_filters( 'wpsl_address_formats', $address_formats );
}

/**
 * Make sure the provided map type is valid.
 *
 * If the map type is invalid the default is used ( roadmap ).
 *
 * @since 2.0.0
 * @param  string $map_type The provided map type
 * @return string $map_type A valid map type
 */
function wpsl_valid_map_type( $map_type ) {

    $allowed_map_types = wpsl_get_map_types();

    if ( !array_key_exists( $map_type, $allowed_map_types ) ) {
        $map_type = wpsl_get_default_setting( 'map_type' );
    }

    return $map_type;
}

/**
 * Make sure the provided zoom level is valid.
 *
 * If the zoom level is invalid the default is used ( 3 ).
 *
 * @since 2.0.0
 * @param  string $zoom_level The provided zoom level
 * @return string $zoom_level A valid zoom level
 */
function wpsl_valid_zoom_level( $zoom_level ) {

    $zoom_level = absint( $zoom_level );

    if ( ( $zoom_level < 1 ) || ( $zoom_level > 21 ) ) {
        $zoom_level = wpsl_get_default_setting( 'zoom_level' );
    }

    return $zoom_level;
}

/**
 * Get the max auto zoom levels for the map.
 *
 * @since 2.0.0
 * @return array $max_zoom_levels The array holding the min - max zoom levels
 */
function wpsl_get_max_zoom_levels() {

    $max_zoom_levels = array();
    $zoom_level = array(
        'min' => 10,
        'max' => 21
    );

    $i = $zoom_level['min'];

    while ( $i <= $zoom_level['max'] ) {
        $max_zoom_levels[$i] = $i;
        $i++;
    }

    return $max_zoom_levels;
}

/**
 * The labels and the values that can be set through the settings page.
 *
 * @since 2.0.0
 * @return array $labels The label names from the settings page.
 */
function wpsl_labels() {

    $labels = array(
        'search',
        'search_btn',
        'preloader',
        'radius',
        'no_results',
        'results',
        'more',
        'directions',
        'no_directions',
        'back',
        'street_view',
        'zoom_here',
        'error',
        'phone',
        'fax',
        'email',
        'url',
        'hours',
        'start',
        'limit',
        'category',
        'category_default'
    );

    return $labels;
}

/**
 * Callback for array_walk_recursive, sanitize items in a multidimensional array.
 *
 * @since 2.0.0
 * @param string  $item The value
 * @param integer $key  The key
 */
function wpsl_sanitize_multi_array( &$item, $key ) {
    $item = sanitize_text_field( $item );
}

/**
 * Check whether the array is multidimensional.
 *
 * @since 2.0.0
 * @param  array    $array The array to check
 * @return boolean
 */
function wpsl_is_multi_array( $array ) {

    foreach ( $array as $value ) {
        if ( is_array( $value ) ) return true;
    }

    return false;
}

/**
 * @since 2.1.1
 * @param string $address  The address to geocode.
 * @return array $response Either a WP_Error or the response from the Geocode API.
 */
function wpsl_call_geocode_api( $address ) {

    $url      = 'https://maps.googleapis.com/maps/api/geocode/json?address=' . urlencode( $address ) . wpsl_get_gmap_api_params( 'server_key', true );
    $response = wp_remote_get( $url );

    return $response;
}

/**
 * Get the latlng for the provided address.
 *
 * This is used to geocode the address set as the start point on
 * the settings page in case the autocomplete fails
 * ( only happens when there is a JS error on the page ),
 * or to get the latlng when the 'start_location' attr is set
 * on the wpsl shortcode.
 *
 * @since 2.2
 * @param string      $address The address to geocode.
 * @return array|void $latlng  The returned latlng or nothing if there was an error.
 */
function wpsl_get_address_latlng( $address ) {

    $latlng   = '';
    $response = wpsl_call_geocode_api( $address );

    if ( !is_wp_error( $response ) ) {
        $response = json_decode( $response['body'], true );

        if ( $response['status'] == 'OK' ) {
            $latlng = $response['results'][0]['geometry']['location']['lat'] . ',' . $response['results'][0]['geometry']['location']['lng'];
        }
    }

    return $latlng;
}

/**
 * Check if there's a transient that holds
 * the coordinates for the passed address.
 *
 * If not, then we geocode the address and
 * set the returned value in the transient.
 *
 * @since 2.2.11
 * @param  string $address The location to geocode
 * @return string $latlng  The coordinates of the geocoded location
 */
function wpsl_check_latlng_transient( $address ) {

    $name_section   = explode( ',', $address );
    $transient_name = 'wpsl_' . trim( strtolower( $name_section[0] ) ) . '_latlng';

    if ( false === ( $latlng = get_transient( $transient_name ) ) ) {
        $latlng = wpsl_get_address_latlng( $address );

        if ( $latlng ) {
            set_transient( $transient_name, $latlng, 0 );
        }
    }

    return $latlng;
}

/**
 * Make sure the shortcode attributes are booleans
 * when they are expected to be.
 *
 * @since 2.0.4
 * @param  array $atts Shortcode attributes
 * @return array $atts Shortcode attributes
 */
function wpsl_bool_check( $atts ) {

    foreach ( $atts as $key => $val ) {
        if ( in_array( $val, array( 'true', '1', 'yes', 'on' ) ) ) {
            $atts[$key] = true;
        } else if ( in_array( $val, array( 'false', '0', 'no', 'off' ) ) ) {
            $atts[$key] = false;
        }
    }

    return $atts;
}

/**
 * Create a string with random characters.
 *
 * @since 2.2.4
 * @param  int    $length       Used length
 * @return string $random_chars Random characters
 */
function wpsl_random_chars( $length = 5 ) {

    $random_chars = substr( str_shuffle( "abcdefghijklmnopqrstuvwxyz" ), 0, $length );

    return $random_chars;
}

/**
 * Deregister other Google Maps scripts.
 *
 * If plugins / themes also include the Google Maps library, then it can cause
 * problems with the autocomplete function on the settings page and break
 * the store locator on the front-end.
 *
 * @since 2.2.4
 * @return void
 */
function wpsl_deregister_other_gmaps() {

    global $wp_scripts;

    foreach ( $wp_scripts->registered as $index => $script ) {
        if ( ( strpos( $script->src, 'maps.google.com' ) !== false ) || ( strpos( $script->src, 'maps.googleapis.com' ) !== false ) && ( $script->handle !== 'wpsl-gmap' ) ) {
            wp_deregister_script( $script->handle );
        }
    }
}

/**
 * Return the used distance unit.
 *
 * @since 2.2.8
 * @return string Either km or mi
 */
function wpsl_get_distance_unit() {

    global $wpsl_settings;

    return apply_filters( 'wpsl_distance_unit', $wpsl_settings['distance_unit'] );
}

/**
 * Find the term ids for the provided term slugs.
 *
 * @since 2.2.10
 * @param  array $cat_list List of term slugs
 * @return array $term_ids The term ids
 */
function wpsl_get_term_ids( $cat_list ) {

    $term_ids = array();
    $cats     = explode( ',', $cat_list );

    foreach ( $cats as $key => $term_slug ) {
        $term_data = get_term_by( 'slug', $term_slug, 'wpsl_store_category' );

        if ( isset( $term_data->term_id ) && $term_data->term_id ) {
            $term_ids[] = $term_data->term_id;
        }
    }

    return $term_ids;
}

/**
 * Get the url to the admin-ajax.php
 *
 * @since 2.2.3
 * @return string $ajax_url URL to the admin-ajax.php possibly with the WPML lang param included.
 */
function wpsl_get_ajax_url() {

    $i18n = new WPSL_i18n();

    $param = '';

    if ( $i18n->wpml_exists() && defined( 'ICL_LANGUAGE_CODE' ) ) {
        $param = '?lang=' . ICL_LANGUAGE_CODE;
    }

    $ajax_url = admin_url( 'admin-ajax.php' . $param );

    return $ajax_url;
}

/**
 * Get a list of the used meta fields.
 *
 * Used by add-ons and the REST-API.
 *
 * @since 2.2.14
 * @param array $args Argument to grab the locations field. See the $defaults structure.
 * @return array $fields
 */
function wpsl_get_location_fields( $args = array() ) {

    // Required to make sure it works with API calls.
    if ( !class_exists( 'WPSL_Metaboxes' ) ) {
        require_once( WPSL_PLUGIN_DIR . 'admin/class-metaboxes.php' );
    }

    $metaboxes   = new WPSL_Metaboxes();
    $meta_fields = $metaboxes->meta_box_fields();

    $fields   = array();
    $defaults = array(
        'exclude'    => array( 'country_iso' ),
        'prefix'     => '',
        'set_values' => true
    );

    /**
     * Parse incoming $args into an array and merge it with $defaults
     */
    $args = wp_parse_args( $args, $defaults );

    foreach ( $meta_fields as $k => $field_section ) {
        foreach ( $field_section as $field_name => $field_value ) {
            if ( in_array( $field_name, $args['exclude'] ) ) {
                continue;
            }
            $fields[$args['prefix'] . $field_name] = ( $args['set_values'] ) ? $field_name : '';
        }
    }
    return $fields;
}