<?php

defined( 'ABSPATH' ) || exit;

class Persian_Woocommerce_Address extends Persian_Woocommerce_Core {

	//public
	public static string $country = 'IR';

	public static array $states = [
		'ABZ' => 'البرز',
		'ADL' => 'اردبیل',
		'EAZ' => 'آذربایجان شرقی',
		'WAZ' => 'آذربایجان غربی',
		'BHR' => 'بوشهر',
		'CHB' => 'چهارمحال و بختیاری',
		'FRS' => 'فارس',
		'GIL' => 'گیلان',
		'GLS' => 'گلستان',
		'HDN' => 'همدان',
		'HRZ' => 'هرمزگان',
		'ILM' => 'ایلام',
		'ESF' => 'اصفهان',
		'KRN' => 'کرمان',
		'KRH' => 'کرمانشاه',
		'NKH' => 'خراسان شمالی',
		'RKH' => 'خراسان رضوی',
		'SKH' => 'خراسان جنوبی',
		'KHZ' => 'خوزستان',
		'KBD' => 'کهگیلویه و بویراحمد',
		'KRD' => 'کردستان',
		'LRS' => 'لرستان',
		'MKZ' => 'مرکزی',
		'MZN' => 'مازندران',
		'GZN' => 'قزوین',
		'QHM' => 'قم',
		'SMN' => 'سمنان',
		'SBN' => 'سیستان و بلوچستان',
		'THR' => 'تهران',
		'YZD' => 'یزد',
		'ZJN' => 'زنجان',
	];

	public array $class;

	//private
	private array $fields = [];

	private array $selected_city = [];

	//private static
	private static $action_priority = 0;

	private static $iran_cities_page = false;

	private static $inline_script_printed = false;

	public function __construct() {
		add_filter( 'woocommerce_get_country_locale', [ $this, 'locales' ] );
		add_filter( 'woocommerce_localisation_address_formats', [ $this, 'address_formats' ] );
		add_filter( 'woocommerce_states', [ $this, 'iran_states' ], 10, 1 );

		if ( PW()->get_options( 'enable_iran_cities', 'yes' ) == 'yes' ) {

			if ( ( $class = [ 'first', 'last' ] ) && PW()->get_options( 'flip_state_city', 'no' ) == 'yes' ) {
				$class = array_reverse( $class );
			}
			$this->class = [ 'state' => $class[0], 'city' => $class[1] ];

			add_filter( 'woocommerce_checkout_fields', [ $this, 'checkout_fields' ] );
			add_filter( 'woocommerce_billing_fields', [ $this, 'billing_fields' ] );
			add_filter( 'woocommerce_shipping_fields', [ $this, 'shipping_fields' ] );

			add_filter( 'woocommerce_form_field_billing_iran_cities', [ $this, 'iran_cities_field' ], 11, 4 );
			add_filter( 'woocommerce_form_field_shipping_iran_cities', [ $this, 'iran_cities_field' ], 11, 4 );

			add_action( 'wp_enqueue_scripts', [ $this, 'external_js' ] );
			add_action( 'wp_footer', [ $this, 'inline_js' ], 0 );
			add_action( 'wp_footer', [ $this, 'force_inline_js' ], 999999 );
		}
	}

	public function locales( $locales ) {
		$locales[ self::$country ] = [
			'state'    => [ 'label' => __( 'Province', 'woocommerce' ) ],
			'postcode' => [ 'label' => __( 'Postcode', 'woocommerce' ) ],
		];

		return $locales;
	}

	public function address_formats( $formats ) {
		$formats[ self::$country ] = "{first_name} {last_name}\n{company}\n{country}\n{state}\n{city}\n{address_1}\n{address_2}\n{postcode}";

		return $formats;
	}

	public function iran_states( $states ) {

		$states[ self::$country ] = self::$states;

		if ( PW()->get_options( 'allowed_states', 'all' ) == 'all' ) {
			return $states;
		}

		$selections = PW()->get_options( 'specific_allowed_states' );

		if ( is_array( $selections ) ) {
			$states[ self::$country ] = array_intersect_key( self::$states, array_flip( $selections ) );
		}

		return $states;
	}

	//--------------------------------------------
	public function checkout_fields( array $fields ): array {

		$this->fields = $fields;

		if ( is_checkout() ) {

			$types = [ 'billing', 'shipping' ];

			foreach ( $types as $type ) {

				if ( ! empty( $fields[ $type ][ $type . '_city' ] ) ) {
					$fields[ $type ][ $type . '_city' ] = $this->modify_city_field( $fields[ $type ][ $type . '_city' ], $type );
				}

				if ( ! empty( $fields[ $type ][ $type . '_state' ] ) ) {
					$fields[ $type ][ $type . '_state' ] = $this->modify_state_field( $fields[ $type ][ $type . '_state' ], $type );
				}
			}
		}

		return $fields;
	}

	public function billing_fields( $fields ) {

		if ( is_wc_endpoint_url( 'edit-address' ) ) {
			$type = 'billing';
			if ( ! empty( $fields[ $type . '_city' ] ) ) {
				$fields[ $type . '_city' ] = $this->modify_city_field( $fields[ $type . '_city' ], $type );
			}
			if ( ! empty( $fields[ $type . '_state' ] ) ) {
				$fields[ $type . '_state' ] = $this->modify_state_field( $fields[ $type . '_state' ], $type );
			}
		}

		return $fields;
	}

	public function shipping_fields( $fields ) {

		if ( is_wc_endpoint_url( 'edit-address' ) ) {
			$type = 'shipping';
			if ( ! empty( $fields[ $type . '_city' ] ) ) {
				$fields[ $type . '_city' ] = $this->modify_city_field( $fields[ $type . '_city' ], $type );
			}
			if ( ! empty( $fields[ $type . '_state' ] ) ) {
				$fields[ $type . '_state' ] = $this->modify_state_field( $fields[ $type . '_state' ], $type );
			}
		}

		return $fields;
	}

	public function modify_state_field( $fields, $type ) {
		$classes = '';
		if ( ! empty( $fields['class'] ) && $classes = $fields['class'] ) {
			$classes = is_array( $classes ) ? implode( ',', $classes ) : $classes;
			$classes = str_ireplace( 'form-row-wide', 'form-row-' . $this->class['state'], $classes );
		}
		$fields['class'] = apply_filters( $type . '_iran_state_class', explode( ',', $classes ), $fields, $type );

		return $fields;
	}

	public function modify_city_field( $fields, $type ) {
		$classes = '';
		if ( ! empty( $fields['class'] ) && $classes = $fields['class'] ) {
			$classes = is_array( $classes ) ? implode( ',', $classes ) : $classes;
			$classes = str_ireplace( 'form-row-wide', 'form-row-' . $this->class['city'], $classes );
		}
		$fields['class']   = apply_filters( $type . '_iran_city_class', explode( ',', $classes ), $fields, $type );
		$fields['type']    = apply_filters( $type . '_iran_city_type', $type . '_iran_cities', $fields, $type );
		$fields['options'] = apply_filters( $type . '_iran_city_options', [ '' => '' ], $fields, $type );

		return $fields;
	}

	public function iran_cities_field( $field, $key, $args, $value ) {

		$type = explode( '_', $args['type'] );
		if ( ! empty( $value ) ) {
			$this->selected_city[] = $value . '_vsh_' . $type[0];
		}

		$required = $args['required'] ? ' <abbr class="required" title="' . esc_attr__( 'required', 'woocommerce' ) . '">*</abbr>' : '';

		$args['label_class'] = [];
		if ( is_string( $args['label_class'] ) ) {
			$args['label_class'] = [ $args['label_class'] ];
		}

		if ( is_null( $value ) ) {
			$value = ! empty( $args['default'] ) ? $args['default'] : '';
		}

		$selected_value = $args['type'] . '_selected_value';
		global ${$selected_value};
		${$selected_value} = $value;

		$custom_attributes = [];
		if ( ! empty( $args['custom_attributes'] ) && is_array( $args['custom_attributes'] ) ) {
			foreach ( $args['custom_attributes'] as $attribute => $attribute_value ) {
				$custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
			}
		}

		if ( ! empty( $args['validate'] ) ) {
			foreach ( $args['validate'] as $validate ) {
				$args['class'][] = 'validate-' . $validate;
			}
		}

		$args['placeholder'] = __( 'یک شهر انتخاب کنید', 'woocommerce' );

		$label_id        = $args['id'];
		$field_container = '<p class="form-row %1$s" id="%2$s">%3$s</p>';

		$field = '<select name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" class="state_select ' . esc_attr( implode( ' ', $args['input_class'] ) ) . '" ' . implode( ' ', $custom_attributes ) . ' placeholder="' . esc_attr( $args['placeholder'] ) . '"></select>';

		$field_html = '';

		if ( $args['label'] && 'checkbox' != $args['type'] ) {
			$field_html .= '<label for="' . esc_attr( $label_id ) . '" class="' . esc_attr( implode( ' ', $args['label_class'] ) ) . '">' . $args['label'] . $required . '</label>';
		}

		$field_html .= $field;

		if ( $args['description'] ) {
			$field_html .= '<span class="description">' . esc_attr( $args['description'] ) . '</span>';
		}

		$container_class = 'form-row ' . esc_attr( implode( ' ', $args['class'] ) );
		$container_id    = esc_attr( $args['id'] ) . '_field';

		$after = ! empty( $args['clear'] ) ? '<div class="clear"></div>' : '';

		$iran_cities = sprintf( $field_container, $container_class, $container_id, $field_html ) . $after;

		return apply_filters( 'iran_cities_field_select_input', $iran_cities, $field_container, $container_class, $container_id, $field_html, $field, $key, $args, $value, $after );
	}

	public function external_js() {
		wp_dequeue_script( 'pw-iran-cities' );
		wp_deregister_script( 'pw-iran-cities' );
		wp_register_script( 'pw-iran-cities', apply_filters( 'persian_woo_iran_cities', PW()->plugin_url( 'assets/js/iran_cities.min.js' ) ), false, PW_VERSION, true );

		if ( self::$iran_cities_page = ( is_checkout() || is_wc_endpoint_url( 'edit-address' ) ) ) {
			wp_enqueue_script( 'pw-iran-cities' );
		}
	}

	public function inline_js( $force_inline_js = false ) {
		if ( ! $force_inline_js ) {

			if ( self::$inline_script_printed == 'yes' || ! self::$iran_cities_page || self::$action_priority > 100 ) {
				return;
			}

			if ( ! ( wp_script_is( 'jquery', 'done' ) && ! wp_script_is( 'wc-country-select', 'done' ) ) ) {
				self::$action_priority += 5;
				add_action( 'wp_footer', [ $this, 'inline_js' ], self::$action_priority );

				return;
			}
		}

		self::$inline_script_printed = 'yes';
		$value_index                 = apply_filters( 'iran_cities_value_index', 0 );
		$types                       = [ 'billing', 'shipping' ];
		?>
		<script type="text/javascript">
            if (!window.jQuery) {
                alert("کتابخانه جیکوئری قبل از کدهای مربوط به شهرهای ایران لود نشده است!");
            }
            jQuery(function ($) {
				<?php foreach ($types as $type) :

				$type = esc_attr( $type );

				$selected_value = $type . '_iran_cities_selected_value';
				global ${$selected_value};
				$value = ! empty( ${$selected_value} ) ? ${$selected_value} : '';
				$placeholder = isset( $this->fields[ $type ][ $type . '_city' ]['placeholder'] ) ? $this->fields[ $type ][ $type . '_city' ]['placeholder'] : __( 'City', 'woocommerce' );

				$countries = 'get_' . str_replace( 'billing', 'allowed', $type ) . '_countries';
				$countries = WC()->countries->$countries();
				$iran_exist = isset( $countries[ strtoupper( self::$country ) ] ) || isset( $countries[ strtolower( self::$country ) ] ) || isset( $countries[ ucfirst( self::$country ) ] ) ? 'yes' : 'no';
				$just_iran = count( $countries ) == 1 && $iran_exist == 'yes' ? 'yes' : 'no';
				?>

                var <?php echo esc_attr( $type ); ?>_iran_exist = '<?php echo esc_attr( $iran_exist ); ?>';
                var <?php echo esc_attr( $type ); ?>_just_iran = '<?php echo esc_attr( $just_iran ); ?>';

                $(document.body).on('change', '#<?php echo esc_attr( $type ); ?>_state', function () {

                    if (<?php echo esc_attr( $type ); ?>_iran_exist == 'yes' && (<?php echo esc_attr( $type ); ?>_just_iran || $('#<?php echo esc_attr( $type ); ?>_country').val() == '<?php echo esc_attr( self::$country ); ?>')) {

						<?php echo esc_attr( $type ); ?>_cities = [];
						<?php echo esc_attr( $type ); ?>_cities[0] = new Array('خطا در دریافت شهرها', '0');

                        if (typeof Persian_Woo_iranCities === "function")
							<?php echo esc_attr( $type ); ?>_cities = Persian_Woo_iranCities('' + $('#<?php echo esc_attr( $type ); ?>_state').val() + '');
                        else {
                            alert('تابع مربوط به شهرهای ایران یافت نمیشود. با مدیریت در میان بگذارید.');
                        }

						<?php echo esc_attr( $type ); ?>_cities.sort(function (a, b) {
                            if (a[0] == b[0])
                                return 0;
                            if (a[0] > b[0])
                                return 1;
                            else
                                return -1;
                        });
                        var options = '<option value="-1">انتخاب کنید</option>';
                        var j;
						<?php echo esc_attr( $type ); ?>_selected = '';
                        for (j in <?php echo esc_attr( $type ); ?>_cities) {
                            selected = '';
                            if (<?php echo esc_attr( $type ); ?>_cities[j][<?php echo intval( $value_index ); ?>] == '<?php echo esc_attr( $value );?>') {
                                selected = "selected";
								<?php echo esc_attr( $type ); ?>_selected = '<?php echo esc_attr( $value );?>';
                            }
                            options += "<option value='" + <?php echo esc_attr( $type ); ?>_cities[j][<?php echo intval( $value_index ); ?>] + "' " + selected + ">" + <?php echo esc_attr( $type ); ?>_cities[j][0] + "</option>";
                        }
                        $('#<?php echo esc_attr( $type ); ?>_city').empty();
                        if ($("#<?php echo esc_attr( $type ); ?>_city").is('select')) {
                            $('#<?php echo esc_attr( $type ); ?>_city').append(options);
                        }
                        $('#<?php echo esc_attr( $type ); ?>_city').val(<?php echo esc_attr( $type ); ?>_selected).trigger("change");
                    }
                });
                $('#<?php echo esc_attr( $type ); ?>_state').trigger('change');

                var <?php echo esc_attr( $type ); ?>_city_select = $('#<?php echo esc_attr( $type ); ?>_city_field').html();
                var <?php echo esc_attr( $type ); ?>_city_input = '<input id="<?php echo esc_attr( $type ); ?>_city" name="<?php echo esc_attr( $type ); ?>_city" type="text" class="input-text" value="<?php echo esc_attr( $value );?>" placeholder="<?php echo esc_attr( $placeholder );?>" />';

                $(document.body).on('change', '#<?php echo esc_attr( $type ); ?>_country', function () {
                    var is_iran = $('#<?php echo esc_attr( $type ); ?>_country').val() == '<?php echo esc_attr( self::$country ); ?>' ? 'yes' : 'no';
                    set_iran_cities_field('<?php echo esc_attr( $type ); ?>', is_iran);
                });
                $('#<?php echo esc_attr( $type ); ?>_country').trigger('change');

                if (!$('#<?php echo esc_attr( $type ); ?>_country').length) {
                    set_iran_cities_field('<?php echo esc_attr( $type ); ?>', <?php echo esc_attr( $type ); ?>_just_iran);
                }

                $(document.body).on('change', '#<?php echo esc_attr( $type ); ?>_city', function () {
                    if ($('#<?php echo esc_attr( $type ); ?>_city').val() == 'لطفا استان خود را انتخاب کنید') {
                        if ($().select2 && $('#<?php echo esc_attr( $type ); ?>_state').data('select2'))
                            $('#<?php echo esc_attr( $type ); ?>_state').select2('open');
                    }
                });

				<?php if ( is_checkout() ) {
				wc_enqueue_js( "if ($().select2 && $('#" . $type . "_city').data('select2') && !$('#" . $type . "_state').data('select2'))
                        $('#" . $type . "_state').select2();" );
			} ?>

				<?php endforeach; ?>
                function set_iran_cities_field(type, iran) {
                    if (iran == 'yes') {
                        if (!$('#' + type + '_city').is('select')) {
                            $('#' + type + '_city_field').empty();
                            $('#' + type + '_city_field').html(eval(type + '_city_select'));
                            $('#' + type + '_state').val('').trigger("change");
                            $('#' + type + '_city').val('').trigger("change");
                        }
                    } else {
                        $('#' + type + '_city_field').find('*').not('label').remove();
                        $('#' + type + '_city_field').append(eval(type + '_city_input'));
                        $('#' + type + '_state').val('').trigger("change");
                        $('#' + type + '_city').val('').trigger("change");
                    }
                }

            });
		</script>
		<?php
	}

	public function force_inline_js() {
		if ( self::$inline_script_printed != 'yes' && self::$iran_cities_page && wp_script_is( 'jquery', 'done' ) ) {
			$this->inline_js( true );
		}
	}
}

PW()->address = new Persian_Woocommerce_Address();