import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Enumeration;
import java.util.jar.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.JOptionPane;
import javax.swing.ProgressMonitor;

class InstallerLogin
{
	public static void main(String[] args)
	{
		getIDandPassword();
		
		loginAndInstall(userName, password);
		JOptionPane.showMessageDialog(null, "Finished Installing!", "Installed", JOptionPane.INFORMATION_MESSAGE);
		return;
	}
	
    // modal dialog to get user ID and password
    static void getIDandPassword() {
	        JPanel      connectionPanel;
        String[] ConnectOptionNames = { "Login", "Cancel" };
	 	// Create the labels and text fields.
		JLabel     userNameLabel = new JLabel("User Name:   ", JLabel.RIGHT);
	 	JTextField userNameField = new JTextField("");
		JLabel     passwordLabel = new JLabel("Password:   ", JLabel.RIGHT);
		JTextField passwordField = new JPasswordField("");
		connectionPanel = new JPanel(false);
		connectionPanel.setLayout(new BoxLayout(connectionPanel,
							BoxLayout.X_AXIS));
		JPanel namePanel = new JPanel(false);
		namePanel.setLayout(new GridLayout(0, 1));
		namePanel.add(userNameLabel);
		namePanel.add(passwordLabel);
		JPanel fieldPanel = new JPanel(false);
		fieldPanel.setLayout(new GridLayout(0, 1));
		fieldPanel.add(userNameField);
		fieldPanel.add(passwordField);
		connectionPanel.add(namePanel);
		connectionPanel.add(fieldPanel);
	
	        // Connect or quit
		if(JOptionPane.showOptionDialog(null, connectionPanel, 
	                                        "Minecraft Login",
	                                        JOptionPane.OK_CANCEL_OPTION, 
	                                        JOptionPane.PLAIN_MESSAGE,
	                                        null, ConnectOptionNames, 
	                                        ConnectOptionNames[0]) != 0) 
	        {
		    System.exit(0);
		}
        userName = userNameField.getText();
        password = passwordField.getText();
    }
	
	public static void copyJar(File source, File target) throws IOException
	{
		if(target.exists())
		{
			target.delete();
		}
		target.createNewFile();
		
        // Open the jar file.
        JarFile         jar     = new JarFile(source);
        JarOutputStream outputJar = new JarOutputStream(new FileOutputStream(target));

        // Allocate a buffer for reading entry data.
        byte[] buffer = new byte[1024];
        int    bytesRead;

        for (Enumeration<JarEntry> entries = jar.entries(); entries.hasMoreElements(); )
        {
            JarEntry entry = entries.nextElement();
            if(entry.getName().startsWith("META-INF"))
            {
            	continue;
            }
            InputStream entryStream = jar.getInputStream(entry);
            outputJar.putNextEntry(entry);

            while ((bytesRead = entryStream.read(buffer)) != -1)
            {
            	outputJar.write(buffer, 0, bytesRead);
            }
        }
        
        jar.close();
        outputJar.close();
	}
	
	public static void extractJar(File source, File target) throws IOException
	{
		target.mkdirs();
		// Open the jar file.
        JarFile         jar     = new JarFile(source);

        // Allocate a buffer for reading entry data.
        byte[] buffer = new byte[1024];
        int    bytesRead;

        for (Enumeration<JarEntry> entries = jar.entries(); entries.hasMoreElements(); )
        {
            JarEntry entry = entries.nextElement();
            if(entry.getName().startsWith("META-INF"))
            {
            	continue;
            }
            InputStream entryStream = jar.getInputStream(entry);
            File output = new File(target, entry.getName());
            
            if(output.exists())
            	output.delete();
            output.createNewFile();
            
            FileOutputStream outputStream = new FileOutputStream(output);
            while ((bytesRead = entryStream.read(buffer)) != -1)
            {
            	outputStream.write(buffer, 0, bytesRead);
            }
            outputStream.close();
        }
        jar.close();
	}
	
	public static String excutePost(String targetURL, String urlParameters)
    {
    	HttpURLConnection connection = null;
    	try
    	{   
	        String s;
	        URL url = new URL(targetURL);
	        connection = (HttpURLConnection)url.openConnection();
	        connection.setRequestMethod("POST");
	        connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
	        connection.setRequestProperty("Content-Length", (new StringBuilder()).append(Integer.toString(urlParameters.getBytes().length)).toString());
	        connection.setRequestProperty("Content-Language", "en-US");
	        connection.setUseCaches(false);
	        connection.setDoInput(true);
	        connection.setDoOutput(true);
	        DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
	        wr.writeBytes(urlParameters);
	        wr.flush();
	        wr.close();
	        java.io.InputStream is = connection.getInputStream();
	        BufferedReader rd = new BufferedReader(new InputStreamReader(is));
	        StringBuffer response = new StringBuffer();
	        String line;
	        while((line = rd.readLine()) != null) 
	        {
	            response.append(line);
	            response.append('\r');
	        }
	        rd.close();
	        s = response.toString();
	        if(connection != null)
	            connection.disconnect();
	        return s;
    	}
        catch(Exception e)
        {
	        e.printStackTrace();
	        if(connection != null)
	            connection.disconnect();
	        return null;
        }
    }
	
	static public void loginAndInstall(String userName, String password)
    {
		ProgressMonitor progressMonitor = new ProgressMonitor(null, "Installing AdventureCraft", "", 0, 5);
        String result;
        String parameters;
        try
        {
        	parameters = (new StringBuilder("user=")).append(URLEncoder.encode(userName, "UTF-8")).append("&password=").append(URLEncoder.encode(password, "UTF-8")).append("&version=").append(12).toString();
        }
        catch(Exception e)
        {
        	JOptionPane.showMessageDialog(null, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        	return;
        }
        progressMonitor.setNote("Logging In");
        progressMonitor.setProgress(0);
        result = excutePost("http://www.minecraft.net/game/getversion.jsp", parameters);
        if(result == null)
        {
            JOptionPane.showMessageDialog(null, "Can't connect to minecraft.net", "Error", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
            return;
        }
        if(!result.contains(":"))
        {
        	String msg = result;
            if(result.trim().equals("Bad login"))
            	 msg = "Login failed";
            else
            if(result.trim().equals("Old version"))
            {
            	 msg = "Installer needs to be updated";
            }
            JOptionPane.showMessageDialog(null, msg, "Error", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
            return;
        }
        try
        {
        	progressMonitor.setNote("Downloading minecraft.jar");
            progressMonitor.setProgress(1);
            String values[] = result.split(":");
            
            String mainUrl = "http://s3.amazonaws.com/MinecraftDownload/";
            String download = String.format("%sminecraft.jar?user=%s&ticket=%s", mainUrl, values[2].trim(), values[1].trim());
            downloadFile(download, "minecraft.jar");
            
            File outputBin = new File(".minecraft/bin");
            File minecraftIn = new File("minecraft.jar");
            File minecraftOut = new File(outputBin, "minecraft.jar");
            
            progressMonitor.setNote("Deleting META-INF");
            progressMonitor.setProgress(2);
            copyJar(minecraftIn, minecraftOut);
            minecraftIn.delete();
            
            progressMonitor.setNote("Downloading Natives");
            progressMonitor.setProgress(3);
            
            String osName = System.getProperty("os.name");
            String nativeJar = null;
            if(osName.startsWith("Win"))
                nativeJar = "windows_natives.jar";
            else
            if(osName.startsWith("Linux"))
                nativeJar = "linux_natives.jar";
            else
            if(osName.startsWith("Mac"))
                nativeJar = "macosx_natives.jar";
            else
            if(osName.startsWith("Solaris") || osName.startsWith("SunOS"))
                nativeJar = "solaris_natives.jar";
            
            download = String.format("%s%s", mainUrl, nativeJar);
            downloadFile(download, nativeJar);
            
            File source = new File(nativeJar);
            
            progressMonitor.setNote("Extracting Natives");
            progressMonitor.setProgress(4);
            extractJar(source, new File(outputBin, "natives"));
            
            source.delete();

    		progressMonitor.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
            JOptionPane.showMessageDialog(null, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }
        
        return;
    }
	
	static boolean downloadFile(String downloadSite, String outputFileName)
	{
		try
		{
			URL url = new URL(downloadSite);
			URLConnection urlconnection = url.openConnection();
	        urlconnection.connect();
	        
	        BufferedInputStream bis = null;
	        BufferedOutputStream bos = null;
	        File output = new File(outputFileName);
	        output.mkdirs();
	        if(output.exists())
	        {
	        	output.delete();
	        }
	        output.createNewFile();
	        FileOutputStream fos = new FileOutputStream(output);
	        bis = new BufferedInputStream(urlconnection.getInputStream());
	        bos = new BufferedOutputStream(fos);
	
	        byte[] buffer = new byte[0x10000];
	        int buffersize;
	        while((buffersize = bis.read(buffer, 0, 0x10000)) != -1)
	        {
	            bos.write(buffer, 0, buffersize);
	        }
	        bos.close();
	        return true;
		}
		catch(Exception e)
        {
            e.printStackTrace();
            JOptionPane.showMessageDialog(null, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
            return false;
        }
	}

	static String userName;
	static String password;
}