package trisentis;

import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.JScrollPane;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.BoxLayout;

import javax.swing.text.Document;
import javax.swing.text.BadLocationException;
import javax.swing.text.Style;
import javax.swing.text.StyleContext;
import javax.swing.text.StyleConstants;

import java.awt.Dimension;

import java.util.ResourceBundle;

public class TMathFrame extends JFrame{
    private String newline = "\n";
    private int boardSize;
    private int matrixCount;
    private char[][][] matrixChars;
    private JTextPane textPane;
    private final int maxSteps = 100;
    private JScrollPane paneScrollPane;

    protected JLabel actionLabel;

    public TMathFrame(int boardSize, ResourceBundle langBundle)
    {
        super(langBundle.getString("mathTitle"));

        this.boardSize = boardSize;
        
        matrixChars = new char[maxSteps][boardSize][boardSize];
        matrixCount = 0;
        matrixChars[matrixCount] = initMatrix(matrixChars[matrixCount]);

        
        //Create a TEXT PANE
        textPane = new JTextPane();
        textPane.setEditable(false);
        initStylesForTextPane(textPane);
        createDocument(boardSize, textPane.getDocument());
        paneScrollPane = new JScrollPane(textPane);
        paneScrollPane.setVerticalScrollBarPolicy(
                        JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        paneScrollPane.setPreferredSize(new Dimension((84+boardSize*14), (2*boardSize+2)*17));
        paneScrollPane.setMinimumSize(new Dimension(10, 10));

        JPanel contentPane = new JPanel();
        BoxLayout box = new BoxLayout(contentPane, BoxLayout.X_AXIS);
        contentPane.setLayout(box);
        contentPane.add(paneScrollPane);
        setContentPane(contentPane);
    }

    private Document createDocument(int boardSize, Document doc)
    {
        
        String matrixString = "";
        if (matrixCount<1){
            matrixString = matrix2String(matrixChars, 0, matrixCount);
            
            try {
                doc.remove(0, (boardSize*(boardSize+4)));
            }catch (BadLocationException badLocExc){
//                System.err.println("Couldn't remove first text.");
            }
           
        }else{
            matrixString = matrix2String(matrixChars, matrixCount-2, matrixCount);
            
            try {
                doc.remove(doc.getLength()-(boardSize*(boardSize+4)), (boardSize*(boardSize+4)));
            } catch (BadLocationException badLocExc) {
//                System.err.println("Couldn't remove text.");
            }
        }
        
        try {
                doc.insertString(doc.getLength(), matrixString,
                                 textPane.getStyle("regular"));
        } catch (BadLocationException badLocExc) {
//            System.err.println("Couldn't insert initial text.");
        }

        return doc;
    }

    protected void initStylesForTextPane(JTextPane textPane)
    {
        //Initialize some styles.
        Style def = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);

        Style regular = textPane.addStyle("regular", def);
        StyleConstants.setFontFamily(def, "Monospaced");
    }
    
    private char[][] initMatrix(char[][] matrixChars)
    {
        
        for(int y=0; y<boardSize; y++)
        {
            for(int x=0; x<boardSize; x++)
            {
               matrixChars[y][x]='0';
            }
        }
        return matrixChars;
    }
    
    private String matrix2String(char[][][] matrixChars, int begin, int end)
    {
        boolean alterNate;
        if(begin%2==0){
           alterNate=true;
        }else
        {
            alterNate=false;
        }
        
        String matrixString = "";
        int i;
        for(int matCnt=begin+1; matCnt<=end; matCnt+=2)
        {
            for(int y=0; y<boardSize; y++)
            {
                i=1;
                while(i<=2)
                {
                    matrixString = matrixString+"("+String.valueOf(matrixChars[matCnt-(i%2)][y])+")";
                    if(i==1)
                    {
                        if(y==(int)(boardSize-1)/2)
                        {
                           matrixString=matrixString+"+";
                        }else
                        {
                           matrixString=matrixString+" ";
                        }
                    }else
                    {
                        if(y==(int)(boardSize-1)/2)
                        {
                           matrixString=matrixString+"="+newline;
                        }else
                        {
                           matrixString=matrixString+" "+newline;
                        }
                    }
                    i++;
                }
            }
            matrixString=matrixString+newline;
        }
        
        if((end-begin)%2!=1)
        {
            for(int y=0; y<boardSize; y++)
            {
                matrixString = matrixString+"("+String.valueOf(matrixChars[end][y])+")";
                if(y==(int)(boardSize-1)/2)
                {
                    matrixString=matrixString+"+"+newline;
                }else
                {
                    matrixString=matrixString+" "+newline;
                }
            }
        }
        return matrixString;
    }
    
    private char[][] createTrisentisMatrix(int x, int y)
    {
        char[][] matrixChars = new char[boardSize][boardSize];
        matrixChars = initMatrix(matrixChars);
        
        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(i!=x||j!=y){
                    matrixChars[j][i]='1';
                }
            }
        }
        
        return matrixChars;
    }
    
    private char[][] addMatrix2Matrix(char[][] matrixOne, char[][] matrixTwo)
    {
        char[][] endMatrix = new char[boardSize][boardSize];   
        for(int x=0; x<boardSize; x++)
        {
            for(int y=0; y<boardSize; y++)
            {
                if((matrixOne[y][x]=='1')&&(matrixTwo[y][x]=='1'))
                {
                    endMatrix[y][x]='0';
                }else if((matrixOne[y][x]=='0')&&(matrixTwo[y][x]=='0'))
                {
                    endMatrix[y][x]='0';
                }else
                {
                    endMatrix[y][x]='1';
                }
            }
        }
        
        return endMatrix;
    }
    
    public void updateCalculation(int x, int y)
    {
        if (matrixCount>=maxSteps-2)
        {    
            matrixChars[0]=matrixChars[matrixCount];
            matrixCount=0;
        }
        matrixCount++;
        this.matrixChars[matrixCount]=createTrisentisMatrix(x, y);
        matrixCount++;
        this.matrixChars[matrixCount]=addMatrix2Matrix(matrixChars[matrixCount-1], matrixChars[matrixCount-2]);
        createDocument(boardSize, textPane.getDocument());
        textPane.repaint();
        
    }
    
    public void restartGame()
    {
        matrixCount=0;
        matrixChars[matrixCount]=initMatrix(matrixChars[matrixCount]);
        try{
            textPane.getDocument().remove(0, textPane.getDocument().getLength());
        }catch(BadLocationException bLE){}
        createDocument(boardSize, textPane.getDocument());
        textPane.repaint();
    }
    
    public void setBoardSize(int boardSize)
    {
        this.boardSize=boardSize;
        matrixChars = new char[maxSteps][boardSize][boardSize];
        paneScrollPane.setPreferredSize(new Dimension((84+boardSize*14), (2*boardSize+2)*17));
        this.pack();
    }
    
    
}