/// <summary>
 /// If there is a standard part (that passes test) in the parts of the subtag, move it to the start and return true.
 /// If keepStandardPartInPrivateUse is true, only a part before the first 'x' may be moved.
 /// Return true if an acceptable part was found.
 /// </summary>
 private bool MoveStandardPartToStart(SubTag from, Func <string, bool> test, bool keepStandardPartInPrivateUse)
 {
     foreach (string goodPart in from.AllParts)
     {
         if (keepStandardPartInPrivateUse && goodPart.Equals("x", StringComparison.OrdinalIgnoreCase))
         {
             return(false);
         }
         if (test(goodPart))
         {
             from.RemoveParts(goodPart);
             from.InsertAtStartOfSubtag(goodPart);
             return(true);
         }
     }
     return(false);
 }
        /// <summary>
        /// This is used to move one part if appropriate from the 'from' subtag to private use.
        /// Alternatively, if any part is appropriate for the tag according to the test predicate,
        /// it is moved to the first position (unless it follows an x- and keepStandardPartInPrivateUse is true).
        /// If we didn't find a valid part, but did move something, insert standardPrivateCode at the START of "from".
        /// As a side effect, this method may remove non-alphanumeric characters from the from tag.
        /// (I don't like having such a side effect, but it seems necessary to produce the desired behavior).
        /// </summary>
        private void MoveFirstPartToPrivateUseIfNecessary(SubTag from, Func <string, bool> test, string standardPrivatePart,
                                                          bool keepStandardPartInPrivateUse)
        {
            string part = from.AllParts.FirstOrDefault();

            if (part == null)
            {
                return;                 // nothing to move.
            }
            if (test(part))
            {
                return;                 // no need to move, it is a valid code for its slot.
            }
            if (MoveStandardPartToStart(from, test, keepStandardPartInPrivateUse))
            {
                return;
            }
            // If we exit this loop we need to move the first part to private use.
            // But first strip illegal characters since that may leave nothing to move,
            // or at least nothing of the first part we would otherwise move.
            // We do NOT want to do this BEFORE looking for good parts, because (for example) if we have a
            // region code like U!S-gb, we want to detect 'gb' as a good region code and keep that,
            // rather than fixing U!S to US and then choosing to keep that.
            from.RemoveNonAlphaNumericCharacters();
            // But, now we should scan again. If cleaning out bad characters resulted in a good code,
            // let's put it in the main part of the tag rather than private-use.
            if (MoveStandardPartToStart(from, test, keepStandardPartInPrivateUse))
            {
                return;
            }
            // OK, no good parts left. We will move the first part that is not an X.
            part = FirstNonXPart(from.AllParts);
            if (part == null)
            {
                return;
            }
            _privateUseSubTag.AddToSubtag(part);
            from.RemoveParts(part);
            from.InsertAtStartOfSubtag(standardPrivatePart);
        }
		/// <summary>
		/// If there is a standard part (that passes test) in the parts of the subtag, move it to the start and return true.
		/// If keepStandardPartInPrivateUse is true, only a part before the first 'x' may be moved.
		/// Return true if an acceptable part was found.
		/// </summary>
		private bool MoveStandardPartToStart(SubTag from, Func<string, bool> test, bool keepStandardPartInPrivateUse)
		{
			foreach (var goodPart in from.AllParts)
			{
				if (keepStandardPartInPrivateUse && goodPart.Equals("x", StringComparison.OrdinalIgnoreCase))
					return false;
				if (test(goodPart))
				{
					from.RemoveParts(goodPart);
					from.InsertAtStartOfSubtag(goodPart);
					return true;
				}
			}
			return false;
		}
		/// <summary>
		/// This is used to move one part if appropriate from the 'from' subtag to private use.
		/// Alternatively, if any part is appropriate for the tag according to the test predicate,
		/// it is moved to the first position (unless it follows an x- and keepStandardPartInPrivateUse is true).
		/// If we didn't find a valid part, but did move something, insert standardPrivateCode at the START of "from".
		/// As a side effect, this method may remove non-alphanumeric characters from the from tag.
		/// (I don't like having such a side effect, but it seems necessary to produce the desired behavior).
		/// </summary>
		private void MoveFirstPartToPrivateUseIfNecessary(SubTag from, Func<string, bool> test, string standardPrivatePart,
			bool keepStandardPartInPrivateUse)
		{
			var part = from.AllParts.FirstOrDefault();
			if (part == null)
				return; // nothing to move.
			if (test(part))
				return; // no need to move, it is a valid code for its slot.
			if (MoveStandardPartToStart(from, test, keepStandardPartInPrivateUse))
				return;
			// If we exit this loop we need to move the first part to private use.
			// But first strip illegal characters since that may leave nothing to move,
			// or at least nothing of the first part we would otherwise move.
			// We do NOT want to do this BEFORE looking for good parts, because (for example) if we have a
			// region code like U!S-gb, we want to detect 'gb' as a good region code and keep that,
			// rather than fixing U!S to US and then choosing to keep that.
			from.RemoveNonAlphaNumericCharacters();
			// But, now we should scan again. If cleaning out bad characters resulted in a good code,
			// let's put it in the main part of the tag rather than private-use.
			if (MoveStandardPartToStart(from, test, keepStandardPartInPrivateUse))
				return;
			// OK, no good parts left. We will move the first part that is not an X.
			part = FirstNonXPart(from.AllParts);
			if (part == null)
				return;
			_privateUseSubTag.AddToSubtag(part);
			from.RemoveParts(part);
			from.InsertAtStartOfSubtag(standardPrivatePart);
		}