<?php

/**
 * Switches the translations to the given language.
 *
 * @param string $locale The slug of the language: en, fr, ja, etc.
 * @param   bool $pop    Wether to push or pop the stack of switched languages.
 * @see restore_current_locale()
 *
 * @return bool|string False on failure, language slug on success
 */
function switch_to_locale( $locale, $pop = false ) {
	global $l10n, $wp_locale;
	static $stack = false,           // Numeric array: The stack of languages we've switched to.  Does not include the original language.
	       $translations = false,    // Associative array: References to the translations.  Keyed by language slug.
	       $filters = false,         // Associative array: Functions used to filter
	       $original_locale = false; // String

	if ( false === $stack ) {
		$stack = $translations = $filters = array();
		$original_locale = get_locale();
	}

	// We're restoring to the previous language via wpcom_restore_current_locale()
	if ( $pop ) {
		// The stack is empty, bail
		if ( !array_pop( $stack ) ) {
			return false;
		}

		// Remove all filters
		foreach ( $filters as $filter ) {
			remove_filter( 'locale', $filter );
		}

		if ( $locale = end( $stack ) ) {
			// Add the required filter back
			if ( isset( $filters[$locale] ) ) {
				add_filter( 'locale', $filters[$locale] );
			}
		} else {
			// There's nothing left in the stack: go back to the original.
			$locale = $original_locale;
		}

		// Hack the correct translations in.
		foreach ( array_keys( $l10n ) as $textdomain ) {
			$l10n[$textdomain] =& $translations[$locale][$textdomain];
		}

		// Set up date and number formatting globals
		$wp_locale = new WP_Locale();

		return $locale;
	}

	$current_locale = get_locale();

	// We don't have a reference to the current translations stored here.  This must be the first time this function was called.
	// Store it.
	if ( ! isset( $translations[$current_locale] ) ) {
		foreach ( array_keys( $l10n ) as $textdomain ) {
			$translations[$current_locale][$textdomain] = get_translations_for_domain( $textdomain );
		}
	}

	// No change needed.  Still push to the stack so that a future wpcom_restore_current_locale() call won't break anything.
	if ( $current_locale == $locale ) {
		$stack[] = $locale;
		return $locale;
	}

	// Push to the stack
	$stack[] = $locale;

	// Remove any filters we have attached
	foreach ( $filters as $filter ) {
		remove_filter( 'locale', $filter );
	}

	// Generate the required filter...
	if ( ! isset( $filters[$locale] ) ) {
		$filters[$locale] = function() use( $locale ) {
			return $locale;
		};
	}

	// ... and add it
	add_filter( 'locale', $filters[$locale] );

	if ( isset( $translations[$locale] ) ) {
		// We already have a reference - use it
		foreach ( array_keys( $l10n ) as $textdomain ) {
			$l10n[$textdomain] =& $translations[$locale][$textdomain];
		}
	} else {
		// We don't have a reference to the new translations stored here.  They must not have been generated yet.
		// Create the translations and store a reference.
		foreach ( array_keys( $l10n ) as $textdomain ) {

			unload_textdomain( $textdomain );
			if( $textdomain == 'default' ) {
				load_default_textdomain();
			} else {
				//BLOCKER: how do we get the MO file now?
				load_textdomain( $textdomain, $mo);
				$translations[$locale][$textdomain] = get_translations_for_domain( $textdomain );
			}
		}
	}

	// Set up date and number formatting globals
	$wp_locale = new WP_Locale();

	return $locale;
}

/**
 * Restores the translation language to the previous language in the stack.
 * @uses switch_to_locale()
 *
 * @return bool|string False on failure, language slug on success.
 */
function restore_current_locale() {
	return switch_to_locale( null, true );
}