package language.code;

import background.CommandManager;
import background.VariableManager;
import background.commands.Command;
import background.commands.Cycle;
import background.commands.IfSegment;
import background.commands.Operation;
import background.commands.Read;
import background.commands.VariableCommand;
import background.commands.Write;
import language.CodeLanguage;

public class Pascal extends CodeLanguage {

	public Pascal(CommandManager cm) { super(cm); }
	
	@Override
	public void createDictionary() {
		for (String type: VariableManager.getVariableTypes()) {
			dictionary.put(type, "premenna");
		}
		addToDictionary("var", "premenna");
		addToDictionary("for", "for");
		addToDictionary("if", "if");
		addToDictionary("while", "while");
		addToDictionary("repeat", "repeat");		
		addToDictionary("read", "vstup");
		addToDictionary("write", "vystup");
		addToDictionary("readln", "vstup");
		addToDictionary("writeln", "vystup");

	}
	
	@Override
	public String getRegexForUpdate() {
		return ".*[a-zA-Z\\]] *:=.*"; 			// je daco, co konci pismenom alebo koncom hranatej zatvorky, za tym moze a nemusi byt medzera, potom rovnitko, potom hocico
	}

	@Override
	public String getStringForUpdate() {
		return ":="; 			// je daco, co konci pismenom alebo koncom hranatej zatvorky, za tym moze a nemusi byt medzera, potom rovnitko, potom hocico
	}
	
	@Override
	public String getEOLRegex() {
		return ";";
	}
	
	@Override
	public void recognizeData(String s, Command c) {
		c.vizualize = false;
		switch (c.getType()) {
			case "Variable": {	/* Format: var meno : int; */			
				VariableCommand c2 = (VariableCommand) c;				
				String parts[] = s.split("[ :]+"); 
				c2.name = parts[1].trim();
				
				if (parts[2].toLowerCase().contains("array")) {
					String subparts[] = parts[2].trim().split("[\\[\\] \\.,]+");
					c2.posun = Integer.parseInt(subparts[1].trim());
					c2.sizeNumber = Integer.parseInt(subparts[2].trim())+1;
					if (subparts.length>3) {
						c2.table = true;
						c2.posun2 = Integer.parseInt(subparts[3].trim());
						c2.sizeNumber2 = Integer.parseInt(subparts[4].trim())+1;						
					} else { 
						c2.array = true;						
					}	
					c2.type = parts[4].trim().toLowerCase();					
				} else {									// bude inicializacia zakladnej premennej
					c2.type = parts[2].trim();				
				}
				
				if (c2.type.equals("integer")) c2.type="int";
				
				break;
			}				
			case "Operation": {	/* Format: i=i+10; */			
				Operation c2 = (Operation) c;		
								
				String parts[] = s.split(this.getStringForUpdate(), 2);

				if (parts[0].contains("[")) {						// bude to uprava pola
					parts[0] = parts[0].replace(",", "][");
					String subparts[] = parts[0].trim().split("[\\[\\]]");
					c2.name = subparts[0].trim();
					c2.array = true;					
					c2.setIndex(subparts[1].trim());
					if (subparts.length>2) {
						c2.array = false;
						c2.table = true;
						c2.setIndex2(subparts[3].trim());
					}

				} else {			 						// bude uprava zakladnej premennej
					c2.name = parts[0].trim();				
				}

				c2.decomposeValue(parts[1].trim(), c2.name);
				break;
			}
			case "If": {	/* Format: if podmienka==true then */			
				IfSegment c2 = (IfSegment) c;				
				String parts[] = s.split("[ ]+", 2);
				parts[1] += " ";
				parts[1] = parts[1].replace(" then ", "");
				String x = parts[1].trim();		// odstranim vonkajsie zatvorky				
				c2.setCondition(x);
				break;
			}
			case "While": {	/* Format: while podmienka==true do*/			
				Cycle c2 = (Cycle) c;				
				String parts[] = s.split("[ ]+", 2);
				parts[1] += " ";
				parts[1] = parts[1].replace(" do ", "");
				String x = parts[1].trim();		// odstranim vonkajsie zatvorky
				c2.setCondition(x);
				break;
			}
			case "Repeat": {	/* Format: repeat until (podmienka==true) */			
				Cycle c2 = (Cycle) c;				
				String parts[] = s.split("[ ]+", 3); 				
				String x = parts[2].trim();		// odstranim vonkajsie zatvorky
				c2.setCondition(x);
				break;
			}
			case "For": {	/* Format: for i:=1 to 5 do */			
				Cycle c2 = (Cycle) c;	
				s = s.replaceFirst(" *:= *", ":=").replaceFirst("for ", "").trim();			// odstranila som medzery okolo :=, odstranila som for na zaciatku
				s = s+" ";
				s = s.replace(" do ", "").trim();											// odstranila som do na konci
				
				boolean downto = false;
				String parts[];
				if (s.contains(" downto ")) {
					downto = true;
					parts = s.split(" downto ", 2);  // vznikne spodla a vrchna hranica
				} else {
					parts = s.split(" to ", 2);  // vznikne spodna a vrchna hranica
				}
								
				String subparts[] = parts[0].split(this.getStringForUpdate());				// vznikne premenna a spodna hranica				 								
				String variable = subparts[0].trim();
				String first = subparts[1].trim();				
				String second = parts[1].trim();
				
				if (first.contains("+") || first.contains("-") || first.contains("*") || first.contains("/") || first.contains("%")) {
					first = "("+first+")";
				}
								
				Operation init = (Operation) commandManager.getCommand("Operation", c2.vizualize);								
				Operation inc = (Operation) commandManager.getCommand("Operation", c2.vizualize);
				
				//c2.incrementFirst=true;				
								
				if (!downto) {				
					recognizeData(variable+this.getStringForUpdate()+first, init);
					c2.setCondition(variable+"<="+second);
					recognizeData(variable+this.getStringForUpdate()+variable+"+1", inc);					
				} else {
					recognizeData(variable+this.getStringForUpdate()+first, init);
					c2.setCondition(variable+">="+second);
					recognizeData(variable+this.getStringForUpdate()+variable+"-1", inc);					
				}
				
				c2.init = init;
				c2.increment = inc;
				break;
			}
			case "Read": {   /* Format: read(number) */
				Read c2 = (Read) c;
				String parts[] = s.split("[()]");		
				
				
				if (parts[1].contains("[")) {						// bude to pole
					parts[1] = parts[1].replace(",", "][");
					String subparts[] = parts[1].trim().split("[\\[\\]]");
					c2.name = subparts[0].trim();				
					c2.array = true;					
					c2.setIndex(subparts[1].trim());
					if (subparts.length>2) {				
						c2.table = true;
						c2.array = false;		
						c2.setIndex2(subparts[3].trim());
					}
				} else {			 						// bude zakladna premenna
					c2.name = parts[1].trim();				
				}								
				break;
				
			}
			case "Write": {   /* Format: write("string")   OR   writeln(variable) */				
				Write c2 = (Write) c;
				String parts[] = s.split("[()]");
				parts[1] = parts[1].trim();

				if (parts[1].contains("[")) {						// bude to pole
					parts[1] = parts[1].replace(",", "][");
					String subparts[] = parts[1].trim().split("[\\[\\]]");
					c2.name = subparts[0].trim();				
					c2.array = true;					
					c2.setIndex(subparts[1].trim());
					if (subparts.length>2) {
						c2.table = true;
						c2.array = false;		
						c2.setIndex2(subparts[3].trim());
					}
				} else if ((parts[1].startsWith("\"") && parts[1].endsWith("\"")) || (parts[1].startsWith("'") && parts[1].endsWith("'"))) {			 						
					c2.value = parts[1].replace("\"", "").replace("''", "\"").replace("'", "").replace("\"", "'");
				} else {											// bude zakladna premenna
					c2.name = parts[1].trim();				
				}								
				
				if (parts[0].trim().equalsIgnoreCase("writeln")) { c2.value = c2.value+System.getProperty("line.separator"); }
				break;
				
			}
		}
	}	

	
	
	@Override
	public String changeFormat(String s) {
		s = s.replaceFirst("begin", "").replaceFirst("end\\.", "");		
		return formatProcess(s, "begin", "end;");
	}

}
