/**
 * Title:        Pommeja taivaalta
 * Description:  Geneerinen räiskintäpeli Javalla
 * Copyright:    Copyright (c) 2003
 *
 * @author Juho Makkonen
 * @version 1.0
 */


import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;


/**
 * Luokasta <code>JFrame</code> periytyvä
 * <code>Peli</code> on kehysluokka,jonne
 * elementit sijoitetaan. Pelissä on myös
 * sovelluksen käynnistävä
 * <code>main</code>-metodi.
 *
 * Pelissä käytetyt äänitiedostot on ladattu
 * osoitteesta http://www.freeaudioclips.com.
 * Kuten sivuston nimestä käy ilmi, tiedostot
 * ovat ilmaisia ja vapaasti ladattavissa. 
 */
public class Peli extends JFrame {

    /** Sisältöpaneeli, johon komponentit asetellaan. */
    private Container sisaltoPaneeli;

    /** Peli-ikkunan valikkorivi. */
    private JMenuBar valikkorivi;
    
    /** Valikkorivin valikko. */
    private JMenu valikko;

    /** Valikon kohta "Aloita peli". */
    private JMenuItem aloitaPeli;

    /** Valikon kohta "Keskeytä peli". */
    private JMenuItem keskeytaPeli;

    /** Valikon kohta "Ohjeet". */
    private JMenuItem ohjeet;
    
    /** Valikon kohta "Parhaat tulokset". */
    private JMenuItem parhaatTulokset;

    /** Valikon kohta "Sulje". */
    private JMenuItem sulje;
 
    /** Peliohjeet näyttävä kehys. */ 
    private Ohjekehys ohjekehys;

    /** Pommipaneelissa tapahtuu varsinainen peli. */
    private Pommipaneeli pommipaneeli;

    /** Ruudun alareunassa näkyvä kaupunki. */
    private Kaupunki kaupunki;

    /** Pelin tilaa kuvaava kokonaisluku */
    private int pelinTila = 0;

    
    /**
     * Luo uuden peli-ikkunan. Ikkunasta suurimman osan
     * vie sen yläosassa sijaitseva pommipaneeli.
     * Alaosassa on toinen paneeli, jossa näkyy
     * kaupungin kuva.
     */
    public Peli() {

	// Määritetään ikkunan koko ja otsikko ja sijoitetaan
	// se näytön keskelle.
	this.setSize(700,750);
	this.setTitle("Pommeja taivaalta");
	Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
	this.setLocation((dim.width - getSize().width) / 2,
			 (dim.height - getSize().height) / 2);

	// Lisätään kuuntelija, joka lopettaa pelin
	// suorituksen, kun ikkuna suljetaan. 
	this.addWindowListener(new Lopeta());

	// Lisätään näppäimenpainalluksia kuunteleva
	// kuuntelija.
	this.addKeyListener(new NappainKuuntelija());

	// Luodaan valikkorivin elementit
	valikkorivi = new JMenuBar();
	valikko = new JMenu("Peli");
	aloitaPeli = new JMenuItem("Aloita peli");
	keskeytaPeli = new JMenuItem("Keskeytä peli");
	ohjeet = new JMenuItem("Ohjeet");
	parhaatTulokset = new JMenuItem("Parhaat tulokset");
	sulje = new JMenuItem("Sulje");

	// Asetetaan valikon kohdille kuuntelijat.
	aloitaPeli.addActionListener(new Valikkokuuntelija());
	keskeytaPeli.addActionListener(new Valikkokuuntelija());
	sulje.addActionListener(new Valikkokuuntelija());
	ohjeet.addActionListener(new Valikkokuuntelija());
	parhaatTulokset.addActionListener(new Valikkokuuntelija());

	// Asetetaan valikon kohdat, valikko ja valikkorivi 
	// paikoilleen.
	valikko.add(aloitaPeli);
	valikko.add(keskeytaPeli);
	valikko.add(ohjeet);
	valikko.add(parhaatTulokset);
	valikko.add(sulje);
	valikkorivi.add(valikko);
	Dimension d = new Dimension(700,25);
	valikkorivi.setPreferredSize(d);
	this.setJMenuBar(valikkorivi);

	// Asetetaan sisaltoPaneeli ja sille
	// asettelijaksi BorderLayout.
	sisaltoPaneeli = getContentPane();
	sisaltoPaneeli.setLayout(new BorderLayout());

	// Asetetaan pommipaneeli paikoilleen.
	pommipaneeli = new Pommipaneeli(this);
	sisaltoPaneeli.add(pommipaneeli,BorderLayout.CENTER);
	
	// Asetetaan kaupungin näyttävä paneeli paikoilleen.
	kaupunki = new Kaupunki();
	sisaltoPaneeli.add(kaupunki,BorderLayout.SOUTH);

    }

    
    /** 
     * Palauttaa pelin pommipaneelin.
     *
     * @return pommipaneeli
     */
    public Pommipaneeli annaPommipaneeli() {
	return pommipaneeli;
    }


    /** 
     * Palauttaa pelin tilaa kuvaavan kokonaisluvun.
     * Pelin tila voi olla joko 0, 1 tai 2. 
     * 
     * @return pelin tila
     */
    public int annaPelinTila() {
	return pelinTila;
    }
    

    /**
     * Asettaa pelin tilan sekä vaihtaa valikon
     * kohtien tekstit vastaamaan tilaa.
     *
     * @param tila asetettava tila
     */
    public void asetaPelinTila(int tila) {

	pelinTila = tila;

	if (pelinTila == 0) {
	    aloitaPeli.setText("Aloita peli");
	    keskeytaPeli.setText("Keskeytä peli");
	} else if (pelinTila == 1) {
	    aloitaPeli.setText("Lopeta peli");
	    keskeytaPeli.setText("Keskeytä peli");
	} else if (pelinTila == 2) {
	    aloitaPeli.setText("Lopeta peli");
	    keskeytaPeli.setText("Jatka peliä");
	}

    }
 

    /**
     * Näyttää peliohjeet, jos peli ei ole käynnissä.
     */
    public void naytaOhjeet() {
	if (pelinTila == 0 || pelinTila == 2) {
	    ohjekehys = new Ohjekehys(); 
	    ohjekehys.setVisible(true);
	}
    }


    /**
     * Tekee jotain riippuen siitä, mitä
     * valikon kohtaa on klikattu.
     *
     * @param e klikkaustapahtuma
     */
    public void valikkoKuuntele(ActionEvent e) {

	// Jos klikattu kohta on "Aloita peli", asetetaan
	// pelin tilaksi 1 eli "käynnissä", olettaen
	// että pelin tila klikkaushetkellä on 0
	// eli "ei käynnissä".
	if (e.getActionCommand() == "Aloita peli") {
	    if (pelinTila == 0) {
		asetaPelinTila(1);
	    }

	    // Jos klikattu kohta on "Lopeta peli",
	    // varmistetaan pelaajalta, että hän todella
	    // haluaa lopettaa pelin. Jos näin on,
	    // asetetaan peli alkutilaan.
	} else if (e.getActionCommand() == "Lopeta peli") {
	    if (pelinTila == 1 || pelinTila == 2) {
		int tila = pelinTila;
		asetaPelinTila(2);
		int vastaus = JOptionPane.showConfirmDialog
		    (this,"Haluatko varmasti lopettaa pelin?",
		     "Lopetus",JOptionPane.YES_NO_OPTION);
		if (vastaus == JOptionPane.YES_OPTION) {
		    asetaPelinTila(0);
		    pommipaneeli.alustaPeli();		    
		} else {
		    asetaPelinTila(tila);
		}
	    }

	    // Jos klikattu kohta on "Keskeytä peli" ja
	    // peli on käynnissä, asetetaan pelin tilaksi
	    // 2 eli "keskeytetty".
	} else if (e.getActionCommand() == "Keskeytä peli") {
	    if (pelinTila == 1) {
		asetaPelinTila(2);
	    }

	    // Jos klikattu kohta on "Jatka peliä" ja
	    // pelin tila on "keskeytetty", asetetaan
	    // pelin tilaksi "käynnissä".
	} else if (e.getActionCommand() == "Jatka peliä") {
	    if (pelinTila == 2) {
		asetaPelinTila(1);
	    }	

	    // Jos klikattu kohta on "Ohjeet" eikä peli
	    // ole käynnissä, näytetään ohjeet.
	} else if (e.getActionCommand() == "Ohjeet") {	    
	    naytaOhjeet();	    
	    
	    // Jos klikattu kohta on "Parhaat tulokset" 
	    // eikä peli ole käynnissä, näytetään kymmenen
	    // parasta tulosta.
	} else if (e.getActionCommand() == "Parhaat tulokset") {
	    pommipaneeli.naytaTulokset();

	    // Jos klikattu kohta on "Sulje", varmistetaan
	    // ensin pelaajalta, että hän todella haluaa
	    // sulkea ikkunan. Jos näin on, suljetaan
	    // ikkuna ja lopetetaan sovelluksen suoritus.
	} else if (e.getActionCommand() == "Sulje") {
	    int vastaus = JOptionPane.showConfirmDialog
		(this,"Haluatko varmasti poistua pelistä?",
		 "Lopetus",JOptionPane.YES_NO_OPTION);
	    if (vastaus == JOptionPane.YES_OPTION) {
		System.exit(0);
	    }
	}

    }


    /**
     * Laukaisee ydinlatauksen, jos pelaaja painaa
     * välilyöntiä.
     *
     * @param e painettu näppäin
     */
    public void nappainKuuntele(KeyEvent e) {

	if ((e.getKeyCode() == 32) && pelinTila == 1
	    && (pommipaneeli.annaYdinlataukset() > 0)) {
	    pommipaneeli.annaPommit().removeAllElements();
	    pommipaneeli.asetaPisteet(-50);
	    pommipaneeli.asetaYdinlataukset((pommipaneeli.annaYdinlataukset()-1));
	    pommipaneeli.soitaAani("shipexplode.au");
	}

    }
     


    /**
     * Sisäluokka,joka periytyy luokasta
     * <code>WindowAdapter</code>.
     */
    public class Lopeta extends WindowAdapter {


    /**
     * Lopettaa ohjelman suorituksen, kun
     * ikkuna suljetaan.
     */
	public void windowClosing(WindowEvent e) {
	    System.exit(0);
	}

    }



    /**
     * Sisäluokka, joka toteuttaa rajapinnan
     * <code>ActionListener</code>.
     */
    public class Valikkokuuntelija implements ActionListener {


	/** 
	 * Kun jotain valikon kohtaa klikataan, kutsutaan
	 * pelin metodia
	 * <code>valikkokuuntele(ActionEvent e)</code>.
	 *
	 * @param e kuultu tapahtuma
	 */
	public void actionPerformed(ActionEvent e) {
	    valikkoKuuntele(e);
	}
    }

    
    
    /**
     * Sisäluokka, joka toteuttaa rajapinnan
     * <code>Keylistener</code>.
     */
    public class NappainKuuntelija implements KeyListener {


	/**
	 * Suoritetaan, kun jokin näppäin on painettu
	 * alas. Metodia ei tarvita tässä sovelluksessa,
	 * vaan sille on tehty toteutus ainoastaan
	 * rajapinnan toteuttamiseksi.
	 *
	 * @param e painallustapahtuma
	 */
	public void keyPressed(KeyEvent e) {
	}


	/**
	 * Kun näppäin vapautetaan, kutsutaan pelin metodia
	 * <code>nappainKuuntele(KeyEvent e)</code>.
	 *
	 * @param e painallustapahtuma
	 */
	public void keyReleased(KeyEvent e) {
	    nappainKuuntele(e);
	}


	/** 
	 * Suoritetaan, kun jokin näppäin on painettu
	 * alas ja sitten vapautettu. Metodia ei tarvita
	 * tässä sovelluksessa, vaan sille on tehty toteutus
	 * ainoastaan rajapinnan toteuttamiseksi.
	 *
	 * @param e painallustapahtuma
	 */
	public void keyTyped(KeyEvent e) {
	}

    }
    

    /**
     * Pääohjelmametodi luo uuden pelin, avaa ikkunan
     * ja kutsuu pommipaneelin <code>luoSaie</code>
     * -metodia.
     *
     * @param args merkkijonotaulukko, joka sisältää
     * komentorivisyötteen
     */
    public static void main(String[] args) {
	Peli peli = new Peli();
	peli.show();
	peli.annaPommipaneeli().luoSaie();
    }

}


