using System;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using Axiom.Utils;
using Axiom.Interpreter;
using System.IO;

namespace AxiomUnitTestProject
{

  [TestClass]
  public class AssemblerTests
  {

    [TestMethod]																																																				  
    public void BreakStatementVariant6()
    {
        String expression=@"
        A=1;
        WHILE(A<10)
        {
          BREAK;
          BREAK;
        }";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsFalse(codeRunner.Execute(expression),codeRunner.LastMessage);
    }

    [TestMethod]																																																				  
    public void BreakStatementVariant5()
    {
        String expression=@"
        A=1;
        B=1;
        C=1;
        D=1;
        WHILE(A<10)
        {
          WHILE(B<10)
          {
            WHILE(C<10)
            {
              WHILE(D<10)
              {
                A=A+1;
                B=B+1;
                C=C+1;
                D=D+1;
                IF(D==10)THEN BREAK;
                BREAK;
              }
              BREAK;
            }
            BREAK;
          }
          BREAK;
        }";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("A").Equals(2));
      Assert.IsTrue(codeRunner.GetValue<double>("B").Equals(2));
      Assert.IsTrue(codeRunner.GetValue<double>("C").Equals(2));
      Assert.IsTrue(codeRunner.GetValue<double>("D").Equals(2));
    }

    [TestMethod]																																																				  
    public void BreakStatementVariant4()
    {
       String expression=@"
        A=1;
        B=1;
        WHILE(A<10)
        {
          WHILE(B<10)
          {
            IF(B==100)THEN BREAK;
            B=B+1;
          }
          IF(A==100)THEN BREAK;
          A=A+1;
        }"; 
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("A").Equals(10));
      Assert.IsTrue(codeRunner.GetValue<double>("B").Equals(10));
    }

    [TestMethod]																																																				  
    public void BreakStatementVariant3()
    {
       String expression=@"
        A=1;
        B=1;
        WHILE(A<10)
        {
          WHILE(B<10)
          {
            IF(B==1)THEN BREAK;
            B=B+1;
          }
          IF(A==1)THEN BREAK;
          A=A+1;
        }"; 
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("A").Equals(1));
      Assert.IsTrue(codeRunner.GetValue<double>("B").Equals(1));
    }

    [TestMethod]																																																				  
    public void BreakStatementVariant2()
    {
      String expression=@"
        A=1;
        WHILE(A<10)
        {
          IF(A==1)THEN BREAK;
          A=A+1;
        }
        "; 
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("A").Equals(1));
    }

    [TestMethod]																																																				  
    public void BreakStatementVariant1()
    {
      String expression=@"
        break;
        "; 
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsFalse(codeRunner.Execute(expression),codeRunner.LastMessage);
    }

    [TestMethod]																																																				  
    public void DeclarationStatementVariant3()
    {
      String expression=@"
        DECLARE A;
				DECLARE B;
				B=5;
        DECLARE C;
        D=6;
        "; 
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("D").Equals(6));
    }

    [TestMethod]																																																				  
    public void DeclarationStatementVariant2()
    {
      String expression=@"
        DECLARE A;
				DECLARE B;
				B=5;
        DECLARE C;
        "; 
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("B").Equals(5));
    }

    [TestMethod]																																																				  
    public void DeclarationStatementVariant1()
    {
      String expression=@"
        DECLARE A;
				DECLARE B;
				B=5;
        "; 
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("B").Equals(5));
    }

		[TestMethod]																																																				  
    public void WhileStatementVariant4()
    {
      String expression=@"
        DECLARE A,B;
				A=1;
				B=5;
        ITERATIONS=0;
        WHILE(A<=10)
        {
          B=1;
          WHILE(B<=5)
          {
            B=B+1;
            ITERATIONS=ITERATIONS+1;
          }
          A=A+1;
        }"; 
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("A").Equals(11));
      Assert.IsTrue(codeRunner.GetValue<double>("ITERATIONS").Equals(50));
    }

		[TestMethod]																																																				  
    public void WhileStatementVariant3()
    {
      String expression=@"
        DECLARE A,B;
				A=1;
				B=5;
        WHILE(A<B)
        {
          A=A+1;
        }"; 
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("A").Equals(5));
    }

    [TestMethod]
    public void WhileStatementVariant2()
    {
      String expression="DECLARE A,B;A=1;B=5;WHILE(A<B)A=A+1;";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
			Assert.IsTrue(codeRunner.GetValue<double>("A").Equals(5));
    }

    [TestMethod]
    public void WhileStatementVariant1()
    {
      String expression="DECLARE A,B;A=1;B=5;WHILE(A<B){A=A+1;}";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
			Assert.IsTrue(codeRunner.GetValue<double>("A").Equals(5));
    }

    [TestMethod]
    public void DeclarationsVariant4()
    {
      String expression="DECLARE R,user_a,user_b,user_c;R=7;user_a=66;user_b=66;user_c=66;IF(R>=5){user_a=1;user_b=1;user_c=1;}";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
    }

    [TestMethod]
    public void DeclarationsVariant3()
    {
      String expression="DECLARE VAR1,VAR1;";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsFalse(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.LastMessage.Contains("The variable 'VAR1' has already been declared."));
    }

    [TestMethod]
    public void DeclarationsVariant2()
    {
      String expression="DECLARE VAR1,VAR2;";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
    }

    [TestMethod]
    public void DeclarationsVariant1()
    {
      String expression="DECLARE VAR1;DECLARE VAR2;";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
    }

    [TestMethod]
    public void LowerCall()
    {
      String expression="DECLARE VAR1;VAR1='Hello ';VAR1=TRIM(VAR1);VAR1=LOWER(VAR1);";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("VAR1").Equals("hello"));
    }

    [TestMethod]
    public void UpperCall()
    {
      String expression="DECLARE VAR1;VAR1='Hello ';VAR1=TRIM(VAR1);VAR1=UPPER(VAR1);";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("VAR1").Equals("HELLO"));
    }

    [TestMethod]
    public void TrimCall()
    {
      String expression="DECLARE VAR1;VAR1='Hello ';VAR1=TRIM(VAR1);";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("VAR1").Equals("Hello"));
    }

    [TestMethod]
    public void IfStatementVariant20()
    {
      // There is a missing right paren in the if statement nesting so we expect a syntax error
      String expression="DECLARE VAR1,VAR2,VAR4,RESULT;VAR1='YES';VAR2='NO';VAR4=1;IF((((((VAR1=='YES'))))) THEN RESULT='TRUE' ELSE RESULT='FALSE';";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsFalse(codeRunner.Execute(expression));
      Assert.IsTrue(codeRunner.LastMessage.Contains("<Syntax Error>"));
    }

    [TestMethod]
    public void IfStatementVariant19()
    {
      String expression = "DECLARE a,b;a=1;b=1;IF(1+1)upper('Foo');";
      CodeRunner codeRunner=new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.ParseSymbolsCount.Equals(0),"Expected parse symbols count to be zero.");
    }

    [TestMethod]
    public void IfStatementVariant18()
    {
      String expression="DECLARE VAR1,VAR2,VAR4,RESULT;VAR1=2;IF(VAR1==2) THEN RESULT='TRUE' ELSE RESULT='FALSE';";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("RESULT").Equals("TRUE"));
    }

    [TestMethod]
    public void IfStatementVariant17()
    {
      String expression="DECLARE VAR1,VAR2,VAR4,RESULT;VAR1='YES';VAR2='NO';VAR4=1;IF(VAR1=='YES') THEN RESULT='TRUE' ELSE RESULT='FALSE';";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("RESULT").Equals("TRUE"));
    }

    [TestMethod]
    public void IfStatementVariant16()
    {
      String expression="DECLARE VAR1,VAR2,VAR4,RESULT;VAR1='YES';VAR2='NO';VAR4=1;IF((((((VAR1=='YES')))))) THEN RESULT='TRUE' ELSE RESULT='FALSE';";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("RESULT").Equals("TRUE"));
    }

    [TestMethod]
    public void IfStatementVariant15()
    {
      String expression="DECLARE VAR1,VAR2,VAR4,RESULT;VAR1='YES';VAR2='YES';VAR4=1;IF((VAR1=='YES') AND VAR2=='NO') THEN RESULT='TRUE' ELSE RESULT='FALSE';";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("RESULT").Equals("FALSE"));
    }

    [TestMethod]
    public void IfStatementVariant14()
    {
      String expression="DECLARE VAR1,VAR2,VAR4,RESULT;VAR1='YES';VAR2='YES';VAR4=2;IF(VAR1=='YES' AND (VAR2=='YES') AND VAR4==1) THEN RESULT='TRUE' ELSE RESULT='FALSE';";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("RESULT").Equals("FALSE"));
    }

    [TestMethod]
    public void IfStatementVariant13()
    {
      String expression="DECLARE VAR1,VAR2,VAR4,RESULT;VAR1='YES';VAR2='YES';VAR4=1;IF(VAR1=='YES' AND (VAR2=='YES') AND VAR4==1) THEN RESULT='TRUE' ELSE RESULT='FALSE';";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("RESULT").Equals("TRUE"));
    }

    [TestMethod]
    public void IfStatementVariant12()
    {
      String expression="DECLARE VAR1,VAR2,VAR4,RESULT;VAR1='YES';VAR2='YES';VAR4=1;IF((VAR1=='YES') OR (VAR2=='YES') AND (VAR4==1)) THEN RESULT='TRUE' ELSE RESULT='FALSE';";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("RESULT").Equals("TRUE"));
    }

    [TestMethod]
    public void IfStatementVariant11()
    {
      String expression="DECLARE VAR1,VAR2,VAR4,RESULT;VAR1='NO';VAR2='YES';VAR4=1;IF(VAR1=='YES' OR VAR2=='YES' AND VAR4==2) THEN RESULT='TRUE' ELSE RESULT='FALSE';";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("RESULT").Equals("FALSE"));
    }

    [TestMethod]
    public void IfStatementVariant10()
    {
      String expression="DECLARE VAR1,VAR2,VAR4,RESULT;VAR1='YES';VAR2='YES';VAR4=1;IF(VAR1=='YES' OR VAR2=='YES' AND VAR4==2) THEN RESULT='TRUE' ELSE RESULT='FALSE';";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("RESULT").Equals("TRUE"));
    }

    [TestMethod]
    public void IfStatementVariant9()
    {
      String expression="DECLARE VAR1,VAR2,VAR4,RESULT;VAR1='YES';VAR2='YES';VAR4=2;IF(VAR1=='NO' OR (VAR2=='YES' AND VAR4==1)) THEN RESULT='TRUE' ELSE RESULT='FALSE';";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("RESULT").Equals("FALSE"));
    }

    [TestMethod]
    public void IfStatementVariant8()
    {
      String expression="DECLARE VAR1,VAR2,VAR4,RESULT;VAR1='YES';VAR2='YES';VAR4=1;IF(VAR1=='NO' OR (VAR2=='YES' AND VAR4==1)) THEN RESULT='TRUE' ELSE RESULT='FALSE';";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("RESULT").Equals("TRUE"));
    }

    [TestMethod]
    public void IfStatementVariant7()
    {
      String expression="DECLARE VAR1,VAR2,VAR4,RESULT;VAR1='YES';VAR2='NO';VAR4=2;IF((VAR1=='YES') AND VAR2=='NO' AND VAR4==1) THEN RESULT='TRUE' ELSE RESULT='FALSE';";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("RESULT").Equals("FALSE"));
    }

    [TestMethod]
    public void IfStatementVariant6()
    {
      String expression="DECLARE VAR1,VAR2,VAR4,RESULT;VAR1='YES';VAR2='NO';VAR4=1;IF((VAR1=='YES') AND VAR2=='NO' AND VAR4==1) THEN RESULT='TRUE' ELSE RESULT='FALSE';";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("RESULT").Equals("TRUE"));
    }

    [TestMethod]
    public void IfStatementVariant5()
    {
      String expression="DECLARE A,B,RESULT;A=1;B=2;IF(A==1 AND B==2)THEN RESULT=1 ELSE RESULT=0;";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("RESULT").Equals(1.00));
    }

    [TestMethod]
    public void IfStatementVariant4()
    {
      String expression="DECLARE A,B;A=99;if(A<>99)then B=1 else B=2;";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("B").Equals(2.00));
    }

    [TestMethod]
    public void IfStatementVariant3()
    {
      String expression="DECLARE R,user_a,user_b,user_c;R=7;user_a=66;user_b=66;user_c=66;IF(R>=5){user_a=1;user_b=1;user_c=1;}";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("user_a").Equals(1.00));
      Assert.IsTrue(codeRunner.GetValue<double>("user_b").Equals(1.00));
      Assert.IsTrue(codeRunner.GetValue<double>("user_c").Equals(1.00));
    }

    [TestMethod]
    public void IfStatementVariant2()
    {
      String expression="DECLARE A,B,C;A=1;B=2;C=3;IF(B<A){A=0;B=0;C=0;}ELSE{A=1;B=1;C=1;}";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("A").Equals(1.00));
      Assert.IsTrue(codeRunner.GetValue<double>("B").Equals(1.00));
      Assert.IsTrue(codeRunner.GetValue<double>("C").Equals(1.00));
    }

    [TestMethod]
    public void IfStatementVariant1()
    {
      String expression="R_THRESHHOLD=4;";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      double b = codeRunner.GetValue<double>("R_THRESHHOLD");
      Assert.IsTrue(b.Equals(4.00));
    }

    private class InjectionClass
    {
      public double RMultiple { get { return (CurrentPrice-PurchasePrice)/R; } }  
      public double CurrentPrice{ get; set; }
      public double PurchasePrice{ get; set; }
      public double R { get; set; } 
    }

    [TestMethod]
    public void Injection()
    {
      String expression=@"
        R_THRESHHOLD=4;
        MAX_ATR=3;
        MAX_R=10;
        FACTOR=MAX_ATR/MAX_R;
        MULTIPLIER=MAX_ATR;
        IF(RMultiple>R_THRESHHOLD)
        {
          MULTIPLIER=FACTOR*RMultiple;
        }"; 
        
      InjectionClass injectionClass = new InjectionClass();  
      injectionClass.CurrentPrice=220;
      injectionClass.PurchasePrice=195.90;
      injectionClass.R=5.00;        
         
      CodeRunner codeRunner = new CodeRunner();
      SymbolTable symbolTable=codeRunner.SymbolTable;
      symbolTable.AddObjects(new Object[]{injectionClass}.ToList());
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("MULTIPLIER").Equals(1.446));
    }

    [TestMethod]
    public void Substring()
    {
      String expression="DECLARE CURRENCY,START_INDEX,LENGTH,CURRENCY_CODE;CURRENCY='MXN12345';START_INDEX=1;LENGTH=3;CURRENCY_CODE=SUBSTRING(CURRENCY,START_INDEX,LENGTH);";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("CURRENCY_CODE").Equals("MXN"));
    }

    [TestMethod]
    public void InStatement()
    {
      String expression="DECLARE CURRENCY,A;CURRENCY='MXN';A=CURRENCY in('USD','JPY');";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<bool>("A").Equals(false));
    }

    [TestMethod]
    public void InStatement2()
    {
      String expression="DECLARE CURRENCY,A;CURRENCY='MXN';A=CURRENCY in('USD','JPY','MXN');";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<bool>("A").Equals(true));
    }

    [TestMethod]
    public void NestedParens()
    {
      String expression="DECLARE A,B,C;A=100/50;B=100-(((2*2)*8)*9);";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("B").Equals(-188));
    }

    [TestMethod]
    public void Power()
    {
      String expression="DECLARE A,B,C;A=100;B=.5;C=pow(A,B);";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("C").Equals(10));
    }

    [TestMethod]
    public void OrderOfOperations()
    {
      String expression="DECLARE NUM1;NUM1=3*4*(2+1)";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("NUM1").Equals(36));
    }

    [TestMethod]
    public void NumericalEquality()
    {
      String expression="DECLARE NOTIONAL,DELTA,DELTA_ADJUSTED_NOTIONAL;NOTIONAL=20.00;if(2==2)then DELTA=.01 else DELTA=1.00;";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("DELTA").Equals(.01));
    }

    [TestMethod]
    public void Division()
    {
      String expression="DECLARE NOTIONAL,DELTA,DELTA_ADJUSTED_NOTIONAL;NOTIONAL=1000.00;DELTA=.25;DELTA_ADJUSTED_NOTIONAL=NOTIONAL/DELTA;";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("DELTA_ADJUSTED_NOTIONAL").Equals(4000));
    }

    [TestMethod]
    public void Addition()
    {
      String expression="DECLARE a,b,c;a=100;b=100+a;c=-100;";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("b").Equals(200));
    }

    [TestMethod]
    public void NullCoalescing()
    {
      String expression="DECLARE RESULT,A,B,C,D;A=null;B=null;C='NotNull';RESULT=ISNULL(A,B,C);";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("RESULT").Equals("NotNull"));
    }

    [TestMethod]
    public void DateComparisons()
    {
      String expression="DECLARE RESULT,A,B,C,D;A=CONVERT('01-01-2018','System.DateTime');B=CONVERT('01-02-2018','System.DateTime');IF(A>B) THEN RESULT='01-01-2018 IS GREATER THAN 01-02-2018' ELSE RESULT='01-02-2018 IS GREATER THAN 01-01-2018';";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("RESULT").Equals("01-02-2018 IS GREATER THAN 01-01-2018"));
    }

    [TestMethod]
    public void StringMultiplication()
    {
      String expression="DECLARE A,B,C;A='45';B='2';C=A*B;";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("C").Equals(90.00));
    }

    [TestMethod]
    public void ExponentialNotation()
    {
      String expression="DECLARE OAC;OAC=-3.52E-05;";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("OAC").Equals(-3.52E-05));
    }


    [TestMethod]
    public void StringConcatenation()
    {
      String expression="DECLARE ENTITY_ID,AXIOM_META_TAG;ENTITY_ID=148;IF(ENTITY_ID==148)THEN AXIOM_META_TAG=ENTITY_ID+'_BG' ELSE AXIOM_META_TAG=null;";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("AXIOM_META_TAG").Equals("148_BG"));
    }

    [TestMethod]
    public void StringConcatenation2()
    {
      String expression="DECLARE A,B,C;A='45';B='2';C=A+B;";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("C").Equals("452"));
    }

    [TestMethod]
    public void StringComparison()
    {
      String expression="DECLARE ENTITY_ID;ENTITY_ID='';IF(ENTITY_ID=='')THEN ENTITY_ID='ENTITY_ID IS BLANK'ELSE ENTITY_ID='ENTITY_ID IS NOT BLANK';";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("ENTITY_ID").Equals("ENTITY_ID IS BLANK"));
    }

    [TestMethod]
    public void DateConversion()
    {
      String expression="DECLARE ENTITY_ID,EFFECTIVE_DATE;ENTITY_ID=null;IF(ENTITY_ID==null)THEN EFFECTIVE_DATE=CONVERT('2/1/2024','System.DateTime');";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<DateTime>("EFFECTIVE_DATE").Equals(new DateTime(2024,2,1)));
    }
  
    [TestMethod]
    public void LikeClause()
    {
      String expression="DECLARE FIN.Securities.IndustryClass4,FIN.Securities.Country,FIN.Securities.ISIN;FIN.Securities.ISIN='ARARGE';IF(FIN.Securities.ISIN LIKE 'ARARGE'){FIN.Securities.IndustryClass4 = 'Treasury Bond';FIN.Securities.Country='USD'};";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<string>("FIN.Securities.IndustryClass4").Equals("Treasury Bond"));
      Assert.IsTrue(codeRunner.GetValue<string>("FIN.Securities.Country").Equals("USD"));
    }

     [TestMethod]
    public void AbsoluteValueVariant2()
    {
      String expression="DECLARE VAR1,VAR2,VAR4,RESULT;VAR1=-1;VAR2=-3;VAR2=ABS(VAR2)+1;";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("VAR2").Equals(4));
    }

    [TestMethod]
    public void AbsoluteValueVariant1()
    {
      String expression="DECLARE VAR1,VAR2,VAR4,RESULT;VAR1=((ABS(-1)+2)+3);";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("VAR1").Equals(6));
    }

    [TestMethod]
    public void Multiplication()
    {
      String expression="DECLARE var1,var2,var3,var4;var1=1;var2=2;var3=3;var4=var1*var2*var3*var1*var2*var3*abs(var1);";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("var4").Equals(36.00));
    }

    [TestMethod]
    public void AbsoluteValueConvesion()
    {
      String expression="DECLARE var1,var2,var3,var4;var1=-1;var2=-2;var3=-3;var4=abs(var2)*abs(var2)*abs(var2)*abs(var2)*abs(var2)*abs(var2)*abs(var2)*abs(var2)*abs(var2)*abs(var2)*abs(var2)*abs(var2);";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("var4").Equals(4096.00));
    }


    [TestMethod]
    public void StringToDoubleConvesion()
    {
      String expression="DECLARE var1,var2,var3,var4;var1='2';var2='4';var3='6';var4=CONVERT(var1,'System.Double')*CONVERT(var2,'System.Double')*CONVERT(var3,'System.Double');";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<double>("var1").Equals(2.00));
    }

    [TestMethod]
    public void UpperCaseShouldConvert()
    {
      String expression="DECLARE var1,var2,var3,var4;var1='Hello';var2=' ';var3='World';var4=UPPER(var1)+UPPER(var2)+UPPER(var3)";
      CodeRunner codeRunner = new CodeRunner();
      Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
      Assert.IsTrue(codeRunner.GetValue<String>("var4").Equals("HELLO WORLD"));
    }

    [TestMethod]
    public void AssembleAllUseCases()
    {
      foreach(String expression in TestData.CodeLines())
      {
        CodeRunner codeRunner= new CodeRunner();
        Assert.IsTrue(codeRunner.Execute(expression),codeRunner.LastMessage);
        Assert.IsTrue(codeRunner.ParseSymbolsCount.Equals(0),"Expected parse symbols to be zero.");
      }
    }
  }
}

