//
// Visuzalization module for TETDM 
// TypingCalculation.java Version 0.30
// Copyright(C) 2011 System Interface Laboratory (Hiroshima City University) ALL RIGHTS RESERVED.
//
// This program is provided under the license.
// You should read the README file.
//


package module.VisualizationModules.TypingCalculation;

import source.*;
import source.TextData.*;
import source.Utility.*;


import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;



public class TypingCalculation extends VisualizationModule implements KeyListener, ActionListener
{
    boolean typing,result;
    
    int maxQuestion;
    int questionNumber;
    
    char inputChar, nextChar;
    
    String answers[];
    int seed[];
    int seedA[], seedB[];
    int seed1max = 10, seed2max = 10;
    String inputWord, lastInputWord;
    
    long startTime, endTime;
    double lapTime, lastLapTime;
    
    int totalLength, missed, skipped;
    
    String kuku[];
    String kukuFilename;

	//FOR SCORE
    class Score
    {
        int mode;
        String filename;
        
        int currentRank;
        String stringScores[];
        int scores[];
        
        ////SCORE BEGIN
        int rankMaxNumber = 10;
        
        Score(int mode)
        {
            this.mode = mode;
            filename = myModulePath+"score"+mode+".txt";
            
            initializeScore();
        }
        
        public void initializeScore()
        {
            stringScores = fileReadArray(filename);
            scores = new int[rankMaxNumber];
            
            for(int i=0;i<rankMaxNumber;i++)
                scores[i] = 0;
            for(int i=0;i<stringScores.length && i<rankMaxNumber;i++)
                scores[i] = Integer.parseInt(stringScores[i]);
        }
        
        public void saveScore()
        {
            for(int i=0;i<rankMaxNumber;i++)
                stringScores[i] = Integer.toString(scores[i]);
            fileWriteArray(filename, stringScores, rankMaxNumber);
        }
        
        public int addScoreToRank(int score)
        {
            int rank = rankMaxNumber;
            
            for(int i=0;i<rankMaxNumber;i++)
                if(score > scores[i])
                {
                    rank = i;
                    break;
                }
            
            if(rank == rankMaxNumber)
                return rank;
            
            for(int i=rankMaxNumber-1;i>rank;i--)
                scores[i] = scores[i-1];
            scores[rank] = score;
            
            //        for(int i=0;i<rankMaxNumber;i++)
            //            System.out.println("RANK "+(i+1)+" : "+scores[i]);
            
            return rank;
        }
        ////SCORE END
        
        public void initializeScorefile()
        {
            for(int i=0;i<rankMaxNumber;i++)
            {
                //scores[i] = 100-10*i;
                scores[i] = 10-i;
                stringScores[i] = Integer.toString(scores[i]);
            }
            fileWriteArray(filename, stringScores, rankMaxNumber);
        }
    }

    Score score[];
    
    //FOR MODE
    JPanel buttonPanel;
    JButton button[];
    int selectedMode = 0;
    String buttonNames[] = {"+(1-10)","+(1-100)","-(1-10)","-(1-100)","*(1-9)","/(1-9)"};
    String question[] = {"+","+","-","-","*","/"};
    int buttonNumber = 6;

	public TypingCalculation()
	{
		setModuleID(20003);
		setCategoryID(9);
		setUseMode(1);
		setToolType(1);		
	}

	public void initializePanel()
	{
        buttonPanel = new JPanel(new GridLayout(1,buttonNumber));
        buttonPanel.setBackground(Color.yellow);
        add(buttonPanel, BorderLayout.SOUTH);
        
        button = new JButton[buttonNumber];
        for(int i=0;i<buttonNumber;i++)
        {
            if(isMenuInJapanese())
                button[i] = new JButton(inJapanese[i]);
            else
                button[i] = new JButton(buttonNames[i]);
            button[i].addActionListener(this);
            buttonPanel.add(button[i]);
        }

        addKeyListener(this);
//        answers = fileReadArray(myModulePath+"answer.txt");
        answers = new String[1000];
        for(int i=0;i<1000;i++)
            answers[i] = String.valueOf(i);
		
        score = new Score[buttonNumber];
        for(int i=0;i<buttonNumber;i++)
            score[i] = new Score(i);
        
        kukuFilename = myModulePath+"Japanesekuku.txt";
        kuku = fileReadArray(kukuFilename);
	}	
	
	public void initializeData()
	{
        typing = result = false;
        maxQuestion = 10;
        seed = new int[maxQuestion];
        seedA = new int[maxQuestion];
        seedB = new int[maxQuestion];
	}


	
	public void displayOperations(int optionNumber)
	{
		switch(optionNumber)
		{
			case 0:
				repaint();
				break;
                
            case 1:
                requestFocus();
                startTyping();
                repaint();
                break;
                
            case 2:
                if(typing == false)
                    return;
                
                skipped++;
                totalLength -= answers[seed[questionNumber]].length();
                
                requestFocus();                
                if(questionNumber >= maxQuestion)
                    return;
                
                inputWord = answers[seed[questionNumber]];
                nextTyping();
                
                if(questionNumber == maxQuestion)
                {
                    endTyping();
                    return;
                }
                
                nextChar = answers[seed[questionNumber]].charAt(0);
                repaint();
                break;
                
            case 3: //stop forced
                typing = false;
                
                for(int i=0;i<buttonNumber;i++)
                    button[i].setEnabled(true);
                
                repaint();
                break;
				
			case 4: //initialize
                for(int i=0;i<buttonNumber;i++)
                    score[i].initializeScorefile();
				repaint();
				break;			
		}		
	}
    
    public void setStartTime()
    {
        startTime = System.nanoTime();
    }
    
    public double getDiffTime()
    {
        endTime = System.nanoTime();
        return (double)(endTime - startTime)/1000000000.0;
    }
    
    public void exchange(int seedA[], int seedB[], int i)
    {
        int temp;
        temp = seedA[i];
        seedA[i] = seedB[i];
        seedB[i] = temp;
    }
    
    public void createSeed()
    {
        int seed1[] = {10,100,10,100,9,9};
        int seed2[] = {10,100,10,100,9,9};
        
        seed1max = seed1[selectedMode];
        seed2max = seed2[selectedMode];
        
        
        totalLength = 0;
        for(int i=0;i<maxQuestion;i++)
        {
            switch(selectedMode)
            {
                case 0:
                case 1:
                    seedA[i] = (int)(Math.random() * seed1max) + 1;
                    seedB[i] = (int)(Math.random() * seed2max) + 1;
                    seed[i] = seedA[i] + seedB[i];
                    break;
                    
                case 2:
                case 3:
                    seedA[i] = (int)(Math.random() * seed1max) + 1;
                    seedB[i] = (int)(Math.random() * seed2max) + 1;
                    if(seedA[i] < seedB[i])
                        exchange(seedA, seedB, i);
                    seed[i] = seedA[i] - seedB[i];
                    break;
                    
                case 4:
                    seedA[i] = (int)(Math.random() * seed1max) + 1;
                    seedB[i] = (int)(Math.random() * seed2max) + 1;
                    seed[i] = seedA[i] * seedB[i];
                    break;
                    
                case 5:
                    seedA[i] = (int)(Math.random() * seed1max) + 1;
                    seedB[i] = (int)(Math.random() * seed2max) + 1;
                    seed[i] = seedA[i] * seedB[i];
                    exchange(seedA, seed, i);
                    break;
                    

            }

            
            totalLength += answers[seed[i]].length();
        }
        
    }
    
    public String createQuestionWord(String input, String question)
    {
        String word = input;
        
        for(int i=input.length();i<question.length();i++)
            if(question.charAt(i) == ' ')
                word += " ";
            else
                word += "*";
        
        return word;
    }
    
    public void startTyping()
    {
        typing = true;
        result = false;
        
        for(int i=0;i<buttonNumber;i++)
            button[i].setEnabled(false);
        
        createSeed();
        
        questionNumber = 0;
        missed = 0;
        skipped = 0;
        lastInputWord = inputWord = "";
        
        nextChar = answers[seed[0]].charAt(0);
        
        setStartTime();
        lapTime = lastLapTime = (double)startTime;
    }
	
    public void nextTyping()
    {
        lastInputWord = inputWord;
        inputWord = "";
        questionNumber++;
        
        setMainFocusDouble(getDiffTime());
        repaintOthersByFocus();
    }
    
    public void endTyping()
    {
        lapTime = getDiffTime();
        writeActionLog("Typing ResultTime = "+lapTime);
        typing = false;
        result = true;
        
        for(int i=0;i<buttonNumber;i++)
            button[i].setEnabled(true);
		
//        currentRank = addScoreToRank((int)(totalLength*60/lapTime - missed*10));
        score[selectedMode].currentRank = score[selectedMode].addScoreToRank((int)(totalLength*60/lapTime - missed));
		score[selectedMode].saveScore();
		
        repaint();
    }
	
	//////////DRAWING
	public void drawBackground(Graphics2D g2)
	{
        g2.setColor(new Color(0,128,255));
        g2.fillRect(0,0, sizeX, sizeY);
        
        g2.setFont(new Font(text.getFontName(), Font.BOLD, 40));
        g2.setColor(Color.yellow);
        
        if(isMenuInJapanese())
            g2.drawString(inJapanese[selectedMode],sizeX/2-buttonNames[selectedMode].length()*40/2,50);
        else
            g2.drawString(buttonNames[selectedMode],sizeX/2-buttonNames[selectedMode].length()*40/2,50);
            
        
        
        ImageIcon icon2 = new ImageIcon(myModulePath+"tet1208moto.gif");
        Image image2 = icon2.getImage();
        
        if(typing)
        {
            g2.setColor(Color.white);
            g2.drawLine(20,sizeY/2,sizeX-20,sizeY/2);
        }
        

        g2.drawImage(image2,sizeX/4,sizeY/2+sizeY/4,sizeX/4,sizeY/4,this);
	}
    
	public void drawQuestion(Graphics g2)
    {
   		g2.setFont(new Font(text.getFontName(), Font.BOLD, 80));
        g2.setColor(Color.yellow);
//        g2.drawString(""+(seed[questionNumber]+1),sizeX/2-40,sizeY/4);
        
        String questionWords;
        
        if(isMenuInJapanese())
            questionWords = +seedA[questionNumber]+" "+inJapanese[buttonNumber+selectedMode]+" "+seedB[questionNumber];
        else
            questionWords = +seedA[questionNumber]+" "+question[selectedMode]+" "+seedB[questionNumber];

        int x = sizeX/2-80*questionWords.length()/2;
        
        if(selectedMode == 4)
            questionWords+=("     "+kuku[(seedA[questionNumber]-1)*9+(seedB[questionNumber]-1)]);
            
        g2.drawString(questionWords,x,sizeY/4);
        
        g2.setFont(new Font(text.getFontName(), Font.BOLD, 40));
        g2.setColor(Color.white);
        g2.drawString(createQuestionWord(inputWord, answers[seed[questionNumber]]),20,sizeY/2);
    }
    
	public void drawInputKeywords(Graphics g2)
    {
   		g2.setFont(new Font(text.getFontName(), Font.BOLD, 40));
        g2.setColor(Color.yellow);
        g2.drawString(inputWord,20,sizeY/2);
        g2.setColor(Color.gray);
        g2.drawString(lastInputWord,20,3*sizeY/4);
        
        g2.drawString(" "+nextChar,0,30);
    }
    
	public void drawTime(Graphics g2)
    {
   		g2.setFont(new Font(text.getFontName(), Font.BOLD, 30));
        g2.setColor(Color.yellow);
//        g2.drawString("SCORE = "+((int)(totalLength*60/lapTime - missed*10))+"[points]",20,sizeY/8);
        g2.drawString("SCORE = "+((int)(totalLength*60/lapTime - missed))+"[points]",20,sizeY/8);
        g2.setColor(Color.green);
        g2.drawString("Speed = "+String.format("%.2f",totalLength*60/lapTime)+"[chars/min]",20,sizeY/4);
        g2.drawString("Missed = "+missed+"[times]",20,3*sizeY/8);
        g2.drawString("Words = "+totalLength+"[words]",20,sizeY/2);
        g2.drawString("Time = "+String.format("%.2f",lapTime)+"[sec]",20,5*sizeY/8);
    }
	
	public void drawScores(Graphics g2)
	{
   		g2.setFont(new Font(text.getFontName(), Font.BOLD, 30));
        g2.setColor(Color.white);
		
		for(int i=0;i<score[selectedMode].rankMaxNumber;i++)
		{
			if(i != score[selectedMode].currentRank)
				g2.drawString(String.format("%2d : %6d",i+1,score[selectedMode].scores[i]),sizeX-300,sizeY*(i+1)/11);
			else
			{
				g2.setColor(Color.yellow);				
				g2.drawString(String.format("%2d : %6d",i+1,score[selectedMode].scores[i]),sizeX-300,sizeY*(i+1)/11);
				g2.setColor(Color.white);				
			}
		}
	}	
	
	public void paintComponent(Graphics g)
	{
		
		Graphics2D g2 = (Graphics2D)g;
		
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);// Anti aliasing
		g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);		

		boolean change = getPanelSize();
		
//		if(change)
//			calcu_coordinate();
		 
		
		drawBackground(g2);	//Set background*
        
        if(typing)
        {
            drawQuestion(g2);
            drawInputKeywords(g2);
        }
        
        if(result)
		{
            drawTime(g2);            
			drawScores(g2);
		}           

	}
	

    
	public void update(Graphics g)		//Avoid from blinking
	{
		paintComponent(g);
	}
    

    
	public void keyPressed(KeyEvent e){}
	public void keyReleased(KeyEvent e){}
	public void keyTyped(KeyEvent e)
	{
        if(typing == false)
            return;
        
		inputChar = e.getKeyChar();
        
//        System.out.println("INPUT "+inputChar+" NEXT "+nextChar);

        if(inputChar != nextChar)
        {
            missed++;
            return;
        }
        
        inputWord += inputChar;
        
        if(answers[seed[questionNumber]].length() == inputWord.length())
        {
            nextTyping();
            if(questionNumber == maxQuestion)
            {
                endTyping();
                return;
            }
        }

        nextChar = answers[seed[questionNumber]].charAt(inputWord.length());
        
		repaint();
	}
    
    //Action listener
    public void actionPerformed(ActionEvent e)
    {
        writeButtonLog(e);/////NEW LOG
        
        for(int i=0;i<buttonNumber;i++)
            if(e.getSource() == button[i])
            {
                selectedMode = i;
                repaint();
            }
    }

}
