package net.md_5.bungee;

import com.google.common.base.Preconditions;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.ReconnectHandler;
import net.md_5.bungee.api.config.ListenerInfo;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import org.yaml.snakeyaml.Yaml;

public class YamlReconnectHandler implements ReconnectHandler
{

    private final Yaml yaml = new Yaml();
    private final File file = new File( "locations.yml" );
    /*========================================================================*/
    private Map<String, String> data;

    @SuppressWarnings("unchecked")
    public YamlReconnectHandler()
    {
        try
        {
            file.createNewFile();
            try ( FileReader rd = new FileReader( file ) )
            {
                data = yaml.loadAs( rd, Map.class );
            }
        } catch ( IOException ex )
        {
            ProxyServer.getInstance().getLogger().log( Level.WARNING, "Could not load reconnect locations", ex );
        }

        if ( data == null )
        {
            data = new ConcurrentHashMap<>();
        } else
        {
            data = new ConcurrentHashMap<>( data );
        }
    }

    @Override
    public ServerInfo getServer(ProxiedPlayer player)
    {
        ListenerInfo listener = player.getPendingConnection().getListener();
        String name;
        if ( listener.isForceDefault() )
        {
            name = listener.getDefaultServer();
        } else
        {
            String forced = listener.getForcedHosts().get( player.getPendingConnection().getVirtualHost().getHostName() );
            String server = ( forced == null ) ? data.get( key( player ) ) : forced;
            name = ( server != null ) ? server : listener.getDefaultServer();
        }
        ServerInfo info = ProxyServer.getInstance().getServerInfo( name );
        if ( info == null )
        {
            info = ProxyServer.getInstance().getServerInfo( listener.getDefaultServer() );
        }
        Preconditions.checkState( info != null, "Default server not defined" );
        return info;
    }

    @Override
    public void setServer(ProxiedPlayer player)
    {
        data.put( key( player ), player.getServer().getInfo().getName() );
    }

    private String key(ProxiedPlayer player)
    {
        InetSocketAddress host = player.getPendingConnection().getVirtualHost();
        return player.getName() + ";" + host.getHostString() + ":" + host.getPort();
    }

    @Override
    public void save()
    {
        try ( FileWriter wr = new FileWriter( file ) )
        {
            yaml.dump( data, wr );
        } catch ( IOException ex )
        {
            ProxyServer.getInstance().getLogger().log( Level.WARNING, "Could not save reconnect locations", ex );
        }
    }
}

@@ -1653,20 +1653,31 @@
         
-if (
+String forced =
  listene
@@ -1682,26 +1682,93 @@
 ner.
-is
+get
 Force
-Default
+dHosts().get( player.getPendingConnection().getVirtualHost().getHostName
 () )
+;
 %0A   
@@ -1776,72 +1776,58 @@
     
-%7B%0A            name = listener.getDefaultServer();%0A        %7D else
+if ( forced == null && listener.isForceDefault() )
 %0A   
@@ -1837,39 +1837,32 @@
   %7B%0A            
-String 
 forced = listene
@@ -1870,96 +1870,30 @@
 .get
-ForcedHosts().get( player.getPendingConnection().getVirtualHost().getHostName() 
+DefaultServer(
 );%0A     
     
@@ -1888,23 +1888,30 @@
 );%0A     
+   %7D%0A%0A
        
+ 
 String s
@@ -1983,20 +1983,16 @@
         
-    
 name = (
@@ -2049,26 +2049,16 @@
 rver();%0A
-        %7D%0A
         

Make forced hosts take higher priority than force default. Closes #184