import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

@SuppressWarnings("CheckReturnValue")
public class Execute extends FracLangBaseVisitor<String> {

   public Map<String,String> variables = new HashMap<String,String>();
   Scanner sc = new Scanner(System.in);

   @Override public String visitProgram(FracLangParser.ProgramContext ctx) {
      String res = null;
      return visitChildren(ctx);
   }

   @Override public String visitStatement(FracLangParser.StatementContext ctx) {
      String res = null;
      return visitChildren(ctx);
   }

   @Override public String visitDisplay(FracLangParser.DisplayContext ctx) {
      String value = "";

      if(ctx.expression()!=null){
         value = visit(ctx.expression());
         for (String key: variables.keySet())
         System.out.println(value);
      }
      return visitChildren(ctx);
   }

   public void addVariable(String key,String value){
      variables.put(key, value);
   }

   public String getVariable(String key){
      return variables.get(key);
   }

   @Override public String visitDefineVariable(FracLangParser.DefineVariableContext ctx) {
      String key = "";
      String value = "";

      if(ctx.ID()!=null){
         key = ctx.ID().getText();
         if (visit(ctx.expression())!=null){
            value = visit(ctx.expression());
            addVariable(key, value);
         }
      }

      return visitChildren(ctx);
   }

   @Override public String visitReadExpression(FracLangParser.ReadExpressionContext ctx) {
      String key = ctx.read().ID().getText();
      System.out.print(key + ": ");
      String value = sc.nextLine();
      addVariable(key, value);
      return value;
   }

   @Override public String visitIdExpression(FracLangParser.IdExpressionContext ctx) {
      String value = ctx.ID().getText();
      return getVariable(value);
   }

   @Override public String visitFracExpression(FracLangParser.FracExpressionContext ctx) {
      return ctx.FRAC().getText();
   }

   @Override public String visitUnaryExpression(FracLangParser.UnaryExpressionContext ctx) {
      return "-" + visit(ctx.expression());
   }

   @Override public String visitParenthesisExpression(FracLangParser.ParenthesisExpressionContext ctx) {
      return visit(ctx.expression());
   }

   @Override public String visitAddExpression(FracLangParser.AddExpressionContext ctx) {
      String frac1 = ctx.expression(0).getText();
      String frac2 = ctx.expression(1).getText();
      System.out.println(frac1 + frac2);
      return doMaths(frac1, "+", frac2);
   }

   @Override public String visitSubExpression(FracLangParser.SubExpressionContext ctx) {
      String frac1 = ctx.expression(0).getText();
      String frac2 = ctx.expression(1).getText();  
      return doMaths(frac1, "-", frac2);
   }

   @Override public String visitMultExpression(FracLangParser.MultExpressionContext ctx) {
      String frac1 = ctx.expression(0).getText();
      String frac2 = ctx.expression(1).getText();   
      return doMaths(frac1, "*", frac2);
   }

   @Override public String visitDivExpression(FracLangParser.DivExpressionContext ctx) {
      String frac1 = ctx.expression(0).getText();
      String frac2 = ctx.expression(1).getText();   
      return doMaths(frac1, ":", frac2);
   }

   public String doMaths(String frac1, String op, String frac2){
      String res = "";
      int num = 0;            //numerator
      int den = 1;            //denominator

      String[] parts1 = frac1.split("/");
      String[] parts2 = frac2.split("/");

      //System.out.println(frac1 +" op"+ frac2);

      
      int num1 = Integer.parseInt(parts1[0]);
      int den1 = 1;
      if(parts1[1]!=null){
         den1 = Integer.parseInt(parts1[1]);
      }

      int num2 = Integer.parseInt(parts2[0]);
      int den2 = 1;
      if(parts1[1]!=null){
         den2 = Integer.parseInt(parts2[1]);
      }

      switch (op) {
         case "+":
         num = num1*den2 + num2*den1;
         den = den1*den2;
            break;

         case "-":
         num = num1*den2 - num2*den1;
         den = den1*den2;
            break;
         case "*":
         num = num1*num2;
         den = den1*den2;
            break;
         case ":":
         num = num1*den2;
         den = den1*num2;
            break;
         default:
            break;
      }

      res = num + "/" + den;
      return res;
   }

}
