package me.netux.cachemonet;

import java.awt.Color;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
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.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.File;
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.JFrame;
import javax.swing.JPanel;

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

	private static final Toolkit defaultTk = Toolkit.getDefaultToolkit();
	private static final BufferedImage controls = buffImg("controls.png");
	private static String[] backgrounds, centers;
	private static Image musicMute, musicUnmute, originalWeb;
	private int interval = 0;
	private boolean showKeys = true, mutedMusic = false;
	private String currentBg, currentCenter;
	private Ellipse2D.Double musicControl, originalWebControl;
	private Clip windowdipper;
	
	public static void main(String[] args) {
		String file = Cachemonet.class.getResource("cachemonet-resources").getFile();
		backgrounds = new File(file + "/backgrounds").list();
		centers = new File(file + "/centers").list();
		
		originalWeb = controls.getSubimage(0, 0, 38, 37);
		musicMute = controls.getSubimage(0, 38, 38, 37);
		musicUnmute = controls.getSubimage(0, 76, 38, 37);
		
		new Cachemonet();
	}
	
	public Cachemonet() {
		setTitle("Cachemonet");
		setSize(defaultTk.getScreenSize());
		setIconImage(img("icon.png"));
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setExtendedState(MAXIMIZED_BOTH);
		setCursor(defaultTk.createCustomCursor(img("cursor.png"), new Point(12, 1), "Click Hand"));
		
		final Canvas canvas = new Canvas();
		add(canvas);
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				update();
				while(true) {
					interval++;
					if(interval == 25) {
						interval = 0;
						update();
					}
					
					repaint();
					
					try { Thread.sleep(100); }
					catch (InterruptedException dummyException) { }
				}
			}
		}).start();
		
		canvas.addMouseListener(new MouseListener() {
			
			@Override
			public void mousePressed(MouseEvent e) {
				if(musicControl.contains(e.getPoint())) {
					mutedMusic = !mutedMusic;
					restartMuseek();
					return;
				}
				
				if(originalWebControl.contains(e.getPoint())) {
					try { Desktop.getDesktop().browse(new URI("http://cachemonet.com/")); }
					catch (IOException | URISyntaxException x) { }
					System.exit(0);
					return;
				}
				
				interval = -15;
				update();
			}
			
			@Override
			public void mouseReleased(MouseEvent e) { }
			
			@Override
			public void mouseExited(MouseEvent e) { }
			
			@Override
			public void mouseEntered(MouseEvent e) { }
			
			@Override
			public void mouseClicked(MouseEvent e) { }
			
		});
		
		setVisible(true);
		restartMuseek();
		
		addKeyListener(new KeyListener() {
			
			@Override
			public void keyPressed(KeyEvent e) { if(e.getExtendedKeyCode() == KeyEvent.VK_H) showKeys = !showKeys; }
			
			@Override
			public void keyTyped(KeyEvent e) { }
			
			@Override
			public void keyReleased(KeyEvent e) { }
			
		});
	}
	
	class Canvas extends JPanel {
		
		public int interval = 0;
		
		@Override
		public void paint(Graphics g) {
			Graphics2D g2 = (Graphics2D) g;
			g2.setColor(Color.WHITE);
			g2.fillRect(0, 0, getWidth(), getHeight());
			
			try {
				AffineTransform bgAffTrans = new AffineTransform();
				Dimension bgDim = new Dimension(buffImg(currentBg).getWidth(), buffImg(currentBg).getHeight());
				bgAffTrans.translate(-(bgDim.width / 2), -(bgDim.height / 2));
				for(int y = 0; y * bgDim.height < getHeight() + bgDim.height; y++) {
					int x;
					for(x = 0; x * bgDim.width < getWidth() + bgDim.width; x++) {
						g2.drawImage(img(currentBg), bgAffTrans, null);
						bgAffTrans.translate(bgDim.width, 0);
					}
					bgAffTrans.translate(-(x * bgDim.width), bgDim.height);
				}
				
				AffineTransform centerAffTrans = new AffineTransform();
				centerAffTrans.translate((getWidth() - buffImg(currentCenter).getWidth()) / 2, (getHeight() - buffImg(currentCenter).getHeight()) / 2);
				g2.drawImage(img(currentCenter), centerAffTrans, null);
			} catch(Exception x) { }
			
			if(!showKeys) return;
			g2.drawImage(mutedMusic ? musicUnmute : musicMute, getWidth() - 80, 10, null);
			g2.drawImage(originalWeb, getWidth() - 40, 10, null);
			
			musicControl = new Ellipse2D.Double(getWidth() - 80, 10, 38, 37);
			originalWebControl = new Ellipse2D.Double(getWidth() - 40, 10, 38, 37);
		}
		
	}
	
	private void update() {
		currentBg = "backgrounds/" + backgrounds[(int) (Math.random() * backgrounds.length)];
		currentCenter = "centers/" + centers[(int) (Math.random() * centers.length)];
	}
	
	private void restartMuseek() {
		try {
			if(windowdipper == null) windowdipper = AudioSystem.getClip();
			windowdipper.stop();
			windowdipper.close();
			if(mutedMusic) return;
			windowdipper.open(AudioSystem.getAudioInputStream(getClass().getResource("cachemonet-resources/windowdipper.wav")));
			windowdipper.loop(Clip.LOOP_CONTINUOUSLY);
			windowdipper.start();
		} catch (LineUnavailableException | IOException | UnsupportedAudioFileException x) { }
	}
	
	private static Image img(String f) { return defaultTk.getImage(Cachemonet.class.getResource("cachemonet-resources/" + f)); }
	
	private static BufferedImage buffImg(String f) {
		try { return ImageIO.read(Cachemonet.class.getResource("cachemonet-resources/" + f)); }
		catch (IOException | IllegalArgumentException x) { return null; }
	}
	
}
