package me.netux.tacospin;

import java.awt.Color;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

import javax.imageio.ImageIO;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JComponent;
import javax.swing.JFrame;

@SuppressWarnings("serial")
public class TacoSpin extends JFrame {

	private final Toolkit defaultTk = Toolkit.getDefaultToolkit();
	private final BufferedImage taco = buffImg("taco.jpg"), simpleTaco = buffImg("simple-taco.jpg");
	private final String[] messages = new String[] {
		"You really like tacos!", // 10
		"Holy spinning taco!", // 20
		"One hundred spins! You don't fool around.", // 100
		"Uhhh... taco spin master?", // 1000
		"Nobody likes tacos more than you.", // 100000
		"Time for you to open a taco shop." // 1000000
	};
	private boolean keepItSimple = false, showKeys = true;
	private int tacoDegrees = 0, spins = 0, dummyMessageFade = 1;
	private String msg = "";
	private Clip girlsJustWantToHaveFun;
	
	public static void main(String[] args) { new TacoSpin(); }

	public TacoSpin() {
		setTitle("Taco Spin");
		setSize(defaultTk.getScreenSize());
		setMinimumSize(new Dimension(taco.getWidth() + 100, taco.getHeight() + 100));
		setExtendedState(MAXIMIZED_BOTH);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setLocationRelativeTo(null);
		setIconImage(buffImg("icon.png"));
		
		Canvas canvas = new Canvas();
		add(canvas);
		
		setVisible(true);
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				while(true) {
					tacoDegrees += 4;
					if(tacoDegrees >= 360) {
						spins++;
						tacoDegrees = 0;
					}
					
					switch(spins) {
					case 10: msg = messages[0]; dummyMessageFade = 125; break;
					case 20: msg = messages[1]; dummyMessageFade = 125; break;
					case 100: msg = messages[2]; dummyMessageFade = 125; break;
					case 1000: msg = messages[3]; dummyMessageFade = 125; break;
					case 100000: msg = messages[4]; dummyMessageFade = 125; break;
					case 1000000: msg = messages[5]; dummyMessageFade = 125; break;
					}
					
					if(dummyMessageFade > 0) dummyMessageFade--;
					if(dummyMessageFade == 0) msg = "";
					
					repaint();
					try { Thread.sleep(10); }
					catch (InterruptedException dummyException) { }
				}
			}
		}).start();
		
		addMouseListener(new MouseListener() {
			
			@Override
			public void mouseClicked(MouseEvent e) { if(e.getClickCount() % 2 == 0) keepItSimple = !keepItSimple; }
			
			@Override
			public void mouseReleased(MouseEvent e) { }
			
			@Override
			public void mousePressed(MouseEvent e) { }
			
			@Override
			public void mouseExited(MouseEvent e) { }
			
			@Override
			public void mouseEntered(MouseEvent e) { }
			
		});
		
		addKeyListener(new KeyListener() {
			
			@Override
			public void keyPressed(KeyEvent e) {
				if(e.getExtendedKeyCode() == KeyEvent.VK_H) showKeys = !showKeys;
				if(e.getExtendedKeyCode() == KeyEvent.VK_M) reDoMusicStuff(false);
				
				if(e.getExtendedKeyCode() == KeyEvent.VK_F5) {
					reDoMusicStuff(true);
					spins = 0;
					tacoDegrees = 0;
					msg = "";
					keepItSimple = false;
				}
				
				if(e.getExtendedKeyCode() == KeyEvent.VK_W) {
					try { Desktop.getDesktop().browse(new URI("http://tacospin.com/")); }
					catch (IOException | URISyntaxException x) { }
					System.exit(0);
					return;
				}
				
				repaint();
			}
			
			@Override
			public void keyTyped(KeyEvent e) { }
			
			@Override
			public void keyReleased(KeyEvent e) { }
			
		});
		
		reDoMusicStuff(false);
	}
	
	class Canvas extends JComponent {
		
		@Override
		public void paint(Graphics g) {
			Graphics2D g2 = (Graphics2D) g;
			g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
			g2.setFont(new Font("Arial", Font.PLAIN, 20));
			g2.setColor(Color.WHITE);
			g2.fillRect(0, 0, getWidth(), getHeight());
			
			AffineTransform affTrans = new AffineTransform();
			affTrans.translate(getWidth() / 2, getHeight() / 2);
			affTrans.rotate(Math.toRadians(tacoDegrees));
			g2.setTransform(affTrans);
			g2.drawImage(keepItSimple ? simpleTaco : taco, -(taco.getWidth() / 2), -(taco.getHeight() / 2), null);
			g2.rotate(Math.toRadians(-tacoDegrees));
			
			if(spins > 0) {
				g2.setColor(new Color(255, 255, 255, 80));
				g2.fillOval(-25, -25, 50, 50);
				
				float spinsLocX = -(Integer.toString(spins).length() * (g2.getFont().getSize() / 2.5F)) / 2F, spinsLocY = g2.getFont().getSize() / 2.5F;
				g2.setColor(Color.WHITE);											/* White shadow */
				g2.drawString(Integer.toString(spins), spinsLocX, spinsLocY + 1);	/* behind spins */
				g2.setColor(Color.BLACK);
				g2.drawString(Integer.toString(spins), spinsLocX, spinsLocY);
			}
			
			g2.setFont(g2.getFont().deriveFont(50F));
			g2.setColor(new Color(0, 0, 0, dummyMessageFade * 2));
			g2.drawString(msg, (int) -(g2.getFont().getStringBounds(msg, new FontRenderContext(null, true, false)).getWidth() / 2), (getHeight() / 2) - 50);
			
			if(!showKeys) return;
			g2.setColor(Color.BLACK);
			g2.setFont(new Font("Verdana", Font.PLAIN, 15));
			g2.drawString("W: Go to original webpage", -(getWidth() / 2) + 5, getHeight() / 2 - 35);
			g2.drawString("M: Stop/Restart Music", -(getWidth() / 2) + 5, getHeight() / 2 - 20);
			g2.drawString("F5: Restart everything", -(getWidth() / 2) + 5, getHeight() / 2 - 5);
		}
		
	}
	
	private BufferedImage buffImg(String f) {
		try { return ImageIO.read(getClass().getResource("taco-resources/" + f)); }
		catch(IOException x) { return null; }
	}
	
	private void reDoMusicStuff(boolean restart) {
		try {
			if(girlsJustWantToHaveFun == null) {
				girlsJustWantToHaveFun = AudioSystem.getClip();
				girlsJustWantToHaveFun.open(AudioSystem.getAudioInputStream(getClass().getResource("taco-resources/girls_just_want_to_have_fun.wav")));
			}
			
			if(girlsJustWantToHaveFun.isRunning()) {
				girlsJustWantToHaveFun.stop();
				girlsJustWantToHaveFun.setMicrosecondPosition(0);
				if(restart) girlsJustWantToHaveFun.start();
			} else girlsJustWantToHaveFun.start();
		} catch(IOException | LineUnavailableException | UnsupportedAudioFileException x) { }
	}
	
}
