package diploma;

import javax.swing.*;

//verifică în clauza where și la selecția cp. din select
public class ExprAritmVerifier extends InputVerifier {
	private int row, col;
	private WherePanel wherePanel = null;
	private Interogare interog = null;
//pt. clauza HAVING, trebuie să fie cel puțin o fcț. agregat
	boolean esteCelPutinUnCpInExpr = false;	
	//se apelează cu -1, -1 pt. cp. din select :
	public ExprAritmVerifier(java.awt.Component comp, int row, int col) {
		this.row = row;				
		this.col = col;
		if (comp instanceof WherePanel)
			wherePanel = (WherePanel) comp;
		if (comp instanceof Interogare)
			interog = (Interogare) comp;
	}
	// este nmCp între cp. selectate în interogare ? 
	private boolean eCpSelectat(String nmCp) {
		int size = 0;
		if (wherePanel != null) {
			size = wherePanel.numeCpCBoxModel.getSize();
			for (int i = 0; i < size; i++) {
				if (wherePanel.numeCpCBoxModel.getElementAt(i).toString(
					).equals(nmCp)) {
					return true;
				}
			}
		}
		else {
			size = ((DefaultListModel)interog.selCp2LSi2B.lista1.getModel(
				)).getSize();
			for (int i = 0; i < size; i++) {
				if (((DefaultListModel)interog.selCp2LSi2B.lista1.getModel(
					)).getElementAt(i).toString().equals(nmCp)) {
					return true;
				}
			}
		}
		return false;
	}
	public boolean verify(JComponent input) {
		String exprStr = ((JTextField)input).getText();
		int noPar = 0;	//nr de paranteze
		int ind = 0; 	//parcurge șirul
		char[] separ = {' ', '\t', '+', '-', '*', '/', '(', ')'};
		String ultimulTip = "";	//paranteză, nr, câmp sau operator
		int lung = exprStr.length();
		while (ind < lung) {
			while (exprStr.charAt(ind) == ' ' || exprStr.charAt(ind) 
				== '\t') {
					ind++;
			}
			int primChar = ind;
			char crtChar = exprStr.charAt(primChar);
			if ( crtChar == '+' || crtChar == '-' || crtChar == '*' || 
				crtChar == '/') {
				if (ultimulTip == "operator" || ultimulTip == "") {
					JOptionPane.showMessageDialog(null, "Doi operatori nu "
					 + "pot fi alăturați !", "Eroare sintaxă", 
					 JOptionPane.ERROR_MESSAGE);
					 ((JTextField)input).select(ind, ind + 1);
					 return false;
				}
				else {
					ultimulTip = "operator";
					ind++;
					continue;
				}
			}
			else if (crtChar == '(') {
				if (ultimulTip == "" || ultimulTip == "operator" ||
					ultimulTip == "paranteză deschisă") {
					ultimulTip = "paranteză deschisă";
					noPar++;
					ind++;
					continue;
				}
				else {
					 ((JTextField)input).select(ind, ind + 1);
					 return false;
				}
			}
			else if (crtChar == ')') {
				if ((ultimulTip == "număr" || ultimulTip == "câmp" ||
					ultimulTip == "paranteză închisă") && noPar > 0) {
					ultimulTip = "paranteză închisă";
					noPar--;
					ind++;
					continue;
				}
				else {
					 ((JTextField)input).select(ind, ind + 1);
					 return false;
				}
			}
			else if (Character.isLetter(exprStr.charAt(primChar))) {
				crtChar = exprStr.charAt(ind);
				while (crtChar != ' ' && crtChar != '\t' && crtChar != '+' 
					&& crtChar != '-' && crtChar != '*' && crtChar != '/' 
					&& crtChar != '(' && crtChar != ')' && ind < lung) {
						ind++;
						if (ind < lung)
							crtChar = exprStr.charAt(ind);
				}
				String nmCp = exprStr.substring(primChar, ind);
				if (eCpSelectat(nmCp)) {
					if (ultimulTip == "paranteză deschisă" ||
						ultimulTip == "operator" || ultimulTip == "") {
						ultimulTip = "câmp";
						esteCelPutinUnCpInExpr = true;
						continue;
					}
					else {
						JOptionPane.showMessageDialog(null, "Doi operanzi "
						 + "nu pot fi alăturați !", "Eroare sintaxă", 
						 JOptionPane.ERROR_MESSAGE);
						 ((JTextField)input).select(primChar, ind);
						 return false;
					}
				}
				else 
					JOptionPane.showMessageDialog(null, "Acest câmp nu "
					 + "există între câmpurile selectate !", "Câmp lipsă", 
					 JOptionPane.ERROR_MESSAGE);
					 ((JTextField)input).select(primChar, ind);
					 return false;
			}
			else if (Character.isDigit(exprStr.charAt(primChar))) {
				crtChar = exprStr.charAt(ind);
				while (crtChar != ' ' && crtChar != '\t' && crtChar != '+' 
					&& crtChar != '-' && crtChar != '*' && crtChar != '/' 
					&& crtChar != '(' && crtChar != ')' && ind < lung) {
						ind++;
						if (ind < lung)
							crtChar = exprStr.charAt(ind);
					}
				String numar = exprStr.substring(primChar, ind);
				try {
					double no = Double.parseDouble(numar);
				}
				catch(NumberFormatException e) {
					JOptionPane.showMessageDialog(null, numar + "  nu "
					 + "este un număr !", "Număr eronat", 
					 JOptionPane.ERROR_MESSAGE);
					 ((JTextField)input).select(primChar, ind);
					 return false;
				}
				if (ultimulTip == "operator" || ultimulTip == 
					"paranteză deschisă" || ultimulTip == "") {
					ultimulTip = "număr";
					continue;
				}
				else {
					JOptionPane.showMessageDialog(null, "Eroare sintaxă !",
					"Eroare sintaxă", JOptionPane.ERROR_MESSAGE);
					((JTextField)input).select(primChar, ind);
					return false;
				}

			}
			else {		//nu e permis să fie alte caractere
				 ((JTextField)input).select(ind, ind + 1);
				 return false;
			}
		}
		if (noPar != 0) {
			JOptionPane.showMessageDialog(null, "Nr. parantezelor deschise "
			+ "trebuie să fie egal cu cel al parantezelor închise !",
			"Eroare sintaxă", JOptionPane.ERROR_MESSAGE);
			((JTextField)input).selectAll();
			return false;
		}
		else if (ultimulTip == "operator") {
			((JTextField)input).select(lung - 1, lung);
			return false;
		}
		else {
			if (row > -1 && col > -1) {		//e clauza where sau having
	//e having și nu este nici o fcț. agregată
	 			if(! wherePanel.eWhere && ! esteCelPutinUnCpInExpr) {
	 				wherePanel.exprAritmTxFld.selectAll();
	 				return false;	
	 			}
	 			DefaultCellEditor dce = (DefaultCellEditor)
					wherePanel.criteriiTable.getCellEditor(row, col);
				JComboBox cbb = (JComboBox) dce.getComponent();
				if (! wherePanel.exprAritmTxFld.getText().equals(""))
					((DefaultComboBoxModel)cbb.getModel()).addElement(
						wherePanel.exprAritmTxFld.getText());
				wherePanel.criteriiTable.editCellAt(row, col);
				cbb.setSelectedItem(wherePanel.exprAritmTxFld.getText());
				wherePanel.exprAritmTxFld.setText("");
				wherePanel.exprAritmTxFld.setEnabled(false);	
				wherePanel.exprAritmLabel.setEnabled(false);	
				return true;
			}
			else {			//e selecție de cp. din select
				String expArStr = interog.exprAritmTxFld.getText();
				interog.exprAritmTxFld.setText("");
				interog.exprAritmTxFld.setEnabled(false);	
				interog.exprAritmLabel.setEnabled(false);
				boolean eSuma = false;
				if (interog.selCp2LSi2B.lista1.getSelectedValue().toString(
					).equals("SUM")) {
					expArStr = "SUM(" + expArStr + ")";
					eSuma = true;
				}
				DefaultListModel dlm = (DefaultListModel)
					interog.selCp2LSi2B.lista1.getModel();
				if (! dlm.contains(expArStr))	
					dlm.addElement(expArStr);
				dlm = (DefaultListModel)
					interog.selCp2LSi2B.lista2.getModel();
				if (! dlm.contains(expArStr)) {
					dlm.addElement(expArStr);
					if (eSuma)
						interog.havingWherePanel.numeCpCBoxModel.addElement(
							expArStr);	//agăugăm la tabelul having	
				}	
	//expr. aritm le adăugăm și în tabelul cu clauza where, dacă nu sunt deja
				if (! eSuma) {
					DefaultComboBoxModel dcbm = 
						interog.wherePanel.numeCpCBoxModel;
					boolean eInLista = false;
					for (int i = 0; i < dcbm.getSize(); i++) {
						if (dcbm.getElementAt(i).equals(expArStr))
							eInLista = true;
					}
					if (! eInLista)	
						dcbm.addElement(expArStr);
				//	selCp2LSi2B.lista2.setSelectedValue(expArStr, true);
				}	
				interog.selCp2LSi2B.lista2.setSelectedValue(expArStr, true);
				return true;	
			}
		}
	}
	
	public boolean shouldYieldFocus(JComponent input) {
		return verify(input);
	}
}
