#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

void ucalc_call LogBalance(uCalcBase::Callback cb) {
   // Get the message and the current balance to log
   auto msg = cb.ArgStr(1);
   auto bal = cb.uCalc().Eval("balance");
   cout << "[LOG] " << msg << " | New Balance: " << bal << endl;
}

int main() {
   uCalc uc;
   // 1. Initialize the balance and the logger function
   uc.DefineVariable("balance = 0");
   uc.DefineFunction("LOG(msg As String)", LogBalance);

   // 2. Define DSL rules that also call the LOG function
   auto t = uc.ExpressionTransformer();

   // Each rule now has a side effect: logging its action.
   t.FromTo("DEPOSIT {@Number:amount}",
   "balance = balance + {amount}; LOG('Deposited {amount}')");
   t.FromTo("WITHDRAW {@Number:amount}",
   "balance = balance - {amount}; LOG('Withdrew {amount}')");

   // 3. A longer script to test the log
   auto script = R"(
DEPOSIT 500
WITHDRAW 100
DEPOSIT 250
WITHDRAW 75
)";

   cout << "--- Transaction Log ---" << endl;
   uc.EvalStr(script);
   cout << "-----------------------" << endl;

   cout << "Final Balance: " << uc.Eval("balance") << endl;
}