package trisentis;

/*
 * @(#)Trisentis.java 1.0 03/07/09
 *
 * written by Patrick Thomas in 2003, Paderborn
 */
import java.util.ResourceBundle;
import java.util.Locale;

import java.applet.*;

import java.net.*;

import java.awt.Image;
import javax.swing.ImageIcon;
import java.awt.Graphics;
import java.awt.MediaTracker;
import java.awt.Container;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.Color;
import java.awt.Cursor;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.BorderFactory;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.border.Border;


public class Trisentis extends Applet implements ActionListener, MouseListener{

protected static ResourceBundle langBundle = null;

private static boolean verbose=true;
private JPanel boardPanel, buttonPanel, menuPanel;
private TImageLabel[][] boardLabel;
private JButton restartBtn, solveBtn;
private int boardSize = 4;
private Image btnImage;
private MediaTracker tracker;
private TMenuBar myMenuBar;
private String filePathnName;
private Container mainContainer;
private TMathFrame mathFrame;
private THelpFrame helpFrame;
private TAboutFrame aboutFrame;
private boolean firstTime = true;
private TSolveThread mySolveThread;
private JPanel tempPanel;

public static String userDir;

    public void init()
    {
        filePathnName="trisentis/qcorral.jpg";

        System.out.println("Starting Trisentis...");
        setResourceBundle();

//      constructs the CONTAINER
        mainContainer = new Container();
        BorderLayout mainLayout = new BorderLayout();
        mainContainer.setLayout(mainLayout);

//      constructs the MATHFRAME which is used for showing the matrixes
        mathFrame = new TMathFrame(boardSize, langBundle);
        mathFrame.addWindowListener(new WindowAdapter(){
            public void windowClosing(WindowEvent e) {
                myMenuBar.setCheckBoxMenuItemSelected(false);
                mathFrame.setVisible(false);
            }
        });

        mathFrame.pack();

        helpFrame = new THelpFrame(langBundle, getCodeBase());
        helpFrame.addWindowListener(new WindowAdapter(){
            public void windowClosing(WindowEvent e) {
                helpFrame.setVisible(false);
            }
        });

        aboutFrame = new TAboutFrame(langBundle);
        aboutFrame.addWindowListener(new WindowAdapter(){
            public void windowClosing(WindowEvent e) {
                aboutFrame.setVisible(false);
            }
        });

//      this block constructs the CONTROL BUTTONS for the game and adds them to the maincontainer
        if(verbose) System.out.println("Trisentis: Constructing Controlbuttons");
        GridLayout buttonLayout = new GridLayout(1,2,0,0);
        buttonPanel = new JPanel(buttonLayout);

        restartBtn = new JButton(langBundle.getString("NewGame"));
        restartBtn.addMouseListener(this);
        buttonPanel.add(restartBtn);

        solveBtn = new JButton(langBundle.getString("SolveGame"));
        solveBtn.addMouseListener(this);
        buttonPanel.add(solveBtn);

        mainContainer.add(buttonPanel, BorderLayout.SOUTH);

//      next block constructs the MENU BAR and adds it
        if(verbose) System.out.println("Trisentis: Constructing Menu");
        GridLayout menuLayout = new GridLayout(1,1,0,0);
        menuPanel = new JPanel(menuLayout);
        myMenuBar = new TMenuBar(this, langBundle);
        menuPanel.add(myMenuBar);

        mainContainer.add(menuPanel, BorderLayout.NORTH);

//      adds the BOARD PANEL


        tempPanel = loadBoard();
        mainContainer.add(tempPanel, BorderLayout.CENTER);

        this.add(mainContainer);

        if(verbose) System.out.println("Trisentis: Up and Running");
        this.validate();
    }

    public void start()
    {
        for(int i=0; i<boardSize; i++)
        {
            for(int j=0; j<boardSize; j++)
            {
                boardLabel[i][j].setIconVisible(false);
            }
        }
    }

    public void stop()
    {

    }

    public void destroy()
    {

    }


//-----------------------------------------------

    public Trisentis()
    {
    }

//-----------------------------------------------
//  SETs the LANGUAGE BUNDLE
    protected void setResourceBundle()
    {
        try
        {
            if(verbose) System.out.println("Loading LanguagePackage");

            langBundle = ResourceBundle.getBundle("trisentis.TBundle", Locale.getDefault());
        } catch ( Exception e )
        {
            if(verbose) System.out.println("setResourceBundle: Failed due to Exception!");
        }
    }

//-----------------------------------------------

//  ACTIONLISTENER
    public void actionPerformed(ActionEvent actEvt)
    {

        String commAnd = actEvt.getActionCommand();
        if (commAnd==langBundle.getString("Exit"))
        {
            if(verbose) System.out.println("Trisentis: Quitting...");
            mathFrame.setVisible(false);
            mathFrame.dispose();
            this.setVisible(false);
//            this.dispose();
        }else if(commAnd==langBundle.getString("NewGame"))
        {
            this.restartGame();
        }else if(commAnd==langBundle.getString("SolveGame"))
        {
            this.solveGame();
        }else if (commAnd==langBundle.getString("1Image"))
        {
            loadBoardImages("trisentis/mupad.jpg");
//            this.validate();
            this.restartGame();
        }else if(commAnd==langBundle.getString("2Image"))
        {
            loadBoardImages("trisentis/escher.jpg");
//            this.validate();
            this.restartGame();
        }else if (commAnd==langBundle.getString("3Image"))
        {
            loadBoardImages("trisentis/qcorral.jpg");
//            this.validate();
            this.restartGame();
        }else if(commAnd==langBundle.getString("4Image"))
        {
            loadBoardImages("trisentis/apple.jpg");
//            this.validate();
            this.restartGame();
        }else if(commAnd==langBundle.getString("ShowMathFrame"))
        {

            mathFrame.setVisible(!mathFrame.isVisible());
            ////---mainFrame should get the Focus

        }else if(commAnd==langBundle.getString("Introduction"))
        {

            helpFrame.setVisible(!helpFrame.isVisible());
            ////---mainFrame should get the Focus

        }else if(commAnd==langBundle.getString("About"))
        {

            aboutFrame.setVisible(!aboutFrame.isVisible());

        }else if(commAnd.indexOf("x")!=-1)
        {
            int tempBoardSize = this.boardSize;
            this.boardSize = Integer.parseInt(commAnd.substring(0, commAnd.indexOf("x")));
            JPanel tempJPanel = loadBoard();
            if(tempJPanel!=null){
                mathFrame.setBoardSize(boardSize);
                mainContainer.remove(2);
                mainContainer.add(tempJPanel, BorderLayout.CENTER);

//                this.validate();

                this.restartGame();

            }else{
                this.boardSize = tempBoardSize;
            }
        }
    }

//-----------------------------------------------

//  MOUSELISTENER
    public void mouseReleased(MouseEvent mouEvt)
    {

    }

    public void mousePressed(MouseEvent mouseEvt)
    {
        if(mouseEvt.getComponent()==solveBtn)
        {
            if (solveBtn.isEnabled()==true)
            {
                solveGame();
            }
        }else if(mouseEvt.getComponent()==restartBtn)
        {
            restartGame();
        }
        else if(solveBtn.isEnabled())
        {
        int x=-1, y=-1;
            for(int i=0; i<boardSize; i++)
            {
                for(int j=0; j<boardSize; j++)
                {
                    if(mouseEvt.getComponent()==boardLabel[i][j])
                    {
                        x=i;
                        y=j;
                    }
                }
            }
            fieldPressed(x, y);
        }
    }

    public void mouseExited(MouseEvent mouEvt)
    {
    }

    public void mouseEntered(MouseEvent mouEvt)
    {
    }

    public void mouseClicked(MouseEvent mouEvt)
    {
    }

//-----------------------------------------------

//  manages every reaction for the PRESSED FIELD x,y
    public void fieldPressed(int x, int y)
    {
        int startX, startY;
        if (x<=0)
        {
            startX=0;
        }
        else
        {
            startX=x-1;
        }
        if (y<=0)
        {
            startY=0;
        }
        else
        {
            startY=y-1;
        }


        for(int i=startX; (i<boardSize)&&(i<=x+1); i++)
        {
            for(int j=startY; (j<boardSize)&&(j<=y+1); j++)
            {
                if(x!=i||y!=j){
                    if(boardLabel[i][j].getIcon()==null)
                    {
                        boardLabel[i][j].setIconVisible(true);
                    }else
                    {
                        boardLabel[i][j].setIconVisible(false);
                    }
                }
            }
        }

        mathFrame.updateCalculation(x, y);

        int i=0, j;
        boolean noCovered = true;

        while ((noCovered)&&(i<boardSize))
        {
            j=0;
            while ((noCovered)&&(j<boardSize))
            {
                if (boardLabel[i][j].getIcon()==null)
                {
                    noCovered=false;
                }
                j++;
            }
            i++;
        }
        if (noCovered)
        {
            if(verbose) System.out.println("Trisentis: You Won The Game");
            JOptionPane.showMessageDialog(this, langBundle.getString("Won"));
        }

    }

//-----------------------------------------------

//  RESETS all GAME FIELD to be COVERED
    public void restartGame()
    {

        if (solveBtn.isEnabled()==false){
            try{
                mySolveThread.setReady(true);
            }catch(Exception e){}
        }
        for(int i=0; i<boardSize; i++)
        {
            for(int j=0; j<boardSize; j++)
            {
                boardLabel[i][j].setIconVisible(true);
            }
        }
        this.validate();
        for(int i=0; i<boardSize; i++)
        {
            for(int j=0; j<boardSize; j++)
            {
                boardLabel[i][j].setIconVisible(false);
            }
        }
        mathFrame.restartGame();
    }

//-----------------------------------------------

//  LOADs the specified IMAGE into the BOARD's FIELDs
    public void loadBoardImages(String filepathnname)
    {
         Object[] options = {langBundle.getString("LoadYes"), langBundle.getString("LoadNo")};
        int n = JOptionPane.showOptionDialog(this,
                        langBundle.getString("LoadQuest"),
                        langBundle.getString("LoadTitle"),
                        JOptionPane.YES_NO_OPTION,
                        JOptionPane.QUESTION_MESSAGE,
                        null,
                        options,
                        options[0]);
        if (n == JOptionPane.YES_OPTION){
            filePathnName=filepathnname;
            loadBoardImages();
            this.restartGame();
        }
    }

//  LOADs the IMAGE specified by "filePathnName" into the BOARD's FIELDs
    public void loadBoardImages()
    {
       tracker = new MediaTracker(this);
       URL myURL;

       myURL = getCodeBase();
       //System.out.println("The codebase is : " + myURL.getPath());

       btnImage = getImage(myURL, filePathnName);
       System.out.println("Hier sollte jetzt ein Bild sein: ["+myURL +"]<" + filePathnName + ">");

       tracker.addImage(btnImage, 0);
       if(verbose) System.out.println("Trisentis: Loading Image");

       //waiting for the image to be loaded
       try
       {
            tracker.waitForID(0);
       }catch(java.lang.InterruptedException iRE)
       {
            if(verbose) System.err.println("Tris.: Image Loading has been interrupted.");
       }
       int btnWidth=btnImage.getWidth(this)/boardSize;
       int btnHeight=btnImage.getHeight(this)/boardSize;

       System.out.println("btnDimensions: "+btnWidth+", "+btnHeight);

       if (btnImage.getWidth(this)<20||btnImage.getHeight(this)<80){
            JOptionPane.showMessageDialog(this, langBundle.getString("ImageTooSmall"));
       }else{
           int count = 0;
           this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
           setButtonsEnabled(false);
           for(int y=0; y<boardSize; y++)
           {

               for(int x=0; x<boardSize; x++)
               {
                   count++;
                   boardLabel[x][y].setIcon(btnImage, btnWidth, btnHeight, x, y);
               }
           }
           this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
           setButtonsEnabled(true);
       }
    }

//-----------------------------------------------

//  BUILDS UP a complete NEW BOARD
//  WITH NEW BUTTONS and a NEW IMAGE

    public JPanel loadBoard()
    {
        int optionPaneRes;
        if(firstTime){
            optionPaneRes=JOptionPane.YES_OPTION;
            firstTime=false;
        }else{
        Object[] options = {langBundle.getString("LoadYes"), langBundle.getString("LoadNo")};
        optionPaneRes = JOptionPane.showOptionDialog(this,
                        langBundle.getString("LoadQuest"),
                        langBundle.getString("LoadTitle"),
                        JOptionPane.YES_NO_OPTION,
                        JOptionPane.QUESTION_MESSAGE,
                        null,
                        options,
                        options[0]);
        }
        if (optionPaneRes == JOptionPane.YES_OPTION){
            if(verbose) System.out.println("Ok, your choice. Loading Images.");
            GridLayout boardLayout = new GridLayout(boardSize, boardSize);
            boardLabel= null;
            boardLabel= new TImageLabel[boardSize][boardSize];

            for(int y=0; y<boardSize; y++)
            {
                for(int x=0; x<boardSize; x++)
                {
                    boardLabel[x][y] = new TImageLabel();
                }
            }

            JPanel boardPanel = new JPanel(boardLayout);

            Border boardBorder;
            boardBorder = BorderFactory.createLoweredBevelBorder();
            boardPanel.setBorder(boardBorder);
            boardBorder = BorderFactory.createLineBorder(Color.black);

            loadBoardImages();

            if(verbose) System.out.println("Trisentis: Constructing Board Buttons");
            int buttonWidth=btnImage.getWidth(this)/boardSize;
            int buttonHeight=btnImage.getHeight(this)/boardSize;

            for(int y=0; y<boardSize; y++)
            {
                for(int x=0; x<boardSize; x++)
                {
                    boardLabel[x][y].addMouseListener(this);
                    boardLabel[x][y].setBorder(boardBorder);
                    boardPanel.add(boardLabel[x][y]);
                }
            }

            return boardPanel;

        } else if (optionPaneRes == JOptionPane.NO_OPTION) {
            if(verbose) System.out.println("No? But how to go on?");
            return null;
        } else {
            return loadBoard();
        }
    }

//-----------------------------------------------

//  starts a THREAD that SOLVES the GAME by "REMOTE"
    public void solveGame()
    {
        restartGame();
        this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
        setButtonsEnabled(false);
        if(boardSize%2==1)
        {
            JOptionPane.showMessageDialog(this, langBundle.getString("NotSolvble1")+" "+boardSize+"x"+boardSize+" "+langBundle.getString("NotSolvble2"));
        }
        else
        {
            mySolveThread = new TSolveThread(boardSize, this, langBundle);
            mySolveThread.start();
        }
    }

    public void setButtonsEnabled(boolean isEnabled){
        myMenuBar.setActivated(isEnabled);
        solveBtn.setEnabled(isEnabled);
    }

    public String getAppletInfo() {
        return "Written by Patrick Thomas for "+
                "SciFace GmbH";
    }
}