package net.md_5.bungee.api.chat;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import net.md_5.bungee.api.ChatColor;
import java.util.ArrayList;
import java.util.List;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import lombok.ToString;
@Getter
@Setter
@ToString
@NoArgsConstructor
public class TranslatableComponent extends BaseComponent
{
private final ResourceBundle locales = ResourceBundle.getBundle( "mojang-translations/en_US" );
private final Pattern format = Pattern.compile( "%(?:(\\d+)\\$)?([A-Za-z%]|$)" );
/**
* The key into the Minecraft locale files to use for the translation. The
* text depends on the client's locale setting. The console is always en_US
*/
private String translate;
/**
* The components to substitute into the translation
*/
private List<BaseComponent> with;
/**
* Creates a translatable component from the original to clone it.
*
* @param original the original for the new translatable component.
*/
public TranslatableComponent(TranslatableComponent original)
{
super( original );
setTranslate( original.getTranslate() );
if ( original.getWith() != null )
{
List<BaseComponent> temp = new ArrayList<BaseComponent>();
for ( BaseComponent baseComponent : original.getWith() )
{
temp.add( baseComponent.duplicate() );
}
setWith( temp );
}
}
/**
* Creates a translatable component with the passed substitutions
*
* @see #translate
* @see #setWith(java.util.List)
* @param translate the translation key
* @param with the {@link java.lang.String}s and
* {@link net.md_5.bungee.api.chat.BaseComponent}s to use into the
* translation
*/
public TranslatableComponent(String translate, Object... with)
{
setTranslate( translate );
List<BaseComponent> temp = new ArrayList<BaseComponent>();
for ( Object w : with )
{
if ( w instanceof String )
{
temp.add( new TextComponent( (String) w ) );
} else
{
temp.add( (BaseComponent) w );
}
}
setWith( temp );
}
/**
* Creates a duplicate of this TranslatableComponent.
*
* @return the duplicate of this TranslatableComponent.
*/
@Override
public BaseComponent duplicate()
{
return new TranslatableComponent( this );
}
/**
* Sets the translation substitutions to be used in this component. Removes
* any previously set substitutions
*
* @param components the components to substitute
*/
public void setWith(List<BaseComponent> components)
{
for ( BaseComponent component : components )
{
component.parent = this;
}
with = components;
}
/**
* Adds a text substitution to the component. The text will inherit this
* component's formatting
*
* @param text the text to substitute
*/
public void addWith(String text)
{
addWith( new TextComponent( text ) );
}
/**
* Adds a component substitution to the component. The text will inherit
* this component's formatting
*
* @param component the component to substitute
*/
public void addWith(BaseComponent component)
{
if ( with == null )
{
with = new ArrayList<BaseComponent>();
}
component.parent = this;
with.add( component );
}
@Override
protected void toPlainText(StringBuilder builder)
{
String trans;
try
{
trans = locales.getString( translate );
} catch ( MissingResourceException ex )
{
trans = translate;
}
Matcher matcher = format.matcher( trans );
int position = 0;
int i = 0;
while ( matcher.find( position ) )
{
int pos = matcher.start();
if ( pos != position )
{
builder.append( trans.substring( position, pos ) );
}
position = matcher.end();
String formatCode = matcher.group( 2 );
switch ( formatCode.charAt( 0 ) )
{
case 's':
case 'd':
String withIndex = matcher.group( 1 );
with.get( withIndex != null ? Integer.parseInt( withIndex ) - 1 : i++ ).toPlainText( builder );
break;
case '%':
builder.append( '%' );
break;
}
}
if ( trans.length() != position )
{
builder.append( trans.substring( position, trans.length() ) );
}
super.toPlainText( builder );
}
@Override
protected void toLegacyText(StringBuilder builder)
{
String trans;
try
{
trans = locales.getString( translate );
} catch ( MissingResourceException e )
{
trans = translate;
}
Matcher matcher = format.matcher( trans );
int position = 0;
int i = 0;
while ( matcher.find( position ) )
{
int pos = matcher.start();
if ( pos != position )
{
addFormat( builder );
builder.append( trans.substring( position, pos ) );
}
position = matcher.end();
String formatCode = matcher.group( 2 );
switch ( formatCode.charAt( 0 ) )
{
case 's':
case 'd':
String withIndex = matcher.group( 1 );
with.get( withIndex != null ? Integer.parseInt( withIndex ) - 1 : i++ ).toLegacyText( builder );
break;
case '%':
addFormat( builder );
builder.append( '%' );
break;
}
}
if ( trans.length() != position )
{
addFormat( builder );
builder.append( trans.substring( position, trans.length() ) );
}
super.toLegacyText( builder );
}
private void addFormat(StringBuilder builder)
{
builder.append( getColor() );
if ( isBold() )
{
builder.append( ChatColor.BOLD );
}
if ( isItalic() )
{
builder.append( ChatColor.ITALIC );
}
if ( isUnderlined() )
{
builder.append( ChatColor.UNDERLINE );
}
if ( isStrikethrough() )
{
builder.append( ChatColor.STRIKETHROUGH );
}
if ( isObfuscated() )
{
builder.append( ChatColor.MAGIC );
}
}
}