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

using namespace std;
using namespace uCalcSoftware;

void ucalc_call MoveTurtle(uCalcBase::Callback cb) {
   auto dist = cb.Arg(1);
   auto uc_inst = cb.uCalc();
   auto x = uc_inst.ItemOf("x").Value();
   auto y = uc_inst.ItemOf("y").Value();
   auto angle = uc_inst.ItemOf("angle").Value();
   auto pen_down = uc_inst.ItemOf("pen_down").ValueBool();
   int new_x = x + dist * uc_inst.Eval("CosD(" + to_string(angle) + ")");
   int new_y = y + dist * uc_inst.Eval("SinD(" + to_string(angle) + ")");
   if (pen_down) {
      cout << "Drawing line to (" << new_x << "," << new_y << ")" << endl;
   } else {
      cout << "Moving to (" << new_x << "," << new_y << ")" << endl;
   }
   uc_inst.ItemOf("x").Value(new_x);
   uc_inst.ItemOf("y").Value(new_y);
}

int main() {
   uCalc uc;
   // --- Setup ---
   uc.DefineVariable("x = 0.0");
   uc.DefineVariable("y = 0.0");
   uc.DefineVariable("angle = 90.0");
   uc.DefineVariable("pen_down = false");
   uc.DefineConstant("PI = 3.1415926535");
   uc.DefineFunction("CosD(a) = Cos(a * PI / 180)");
   uc.DefineFunction("SinD(a) = Sin(a * PI / 180)");
   uc.DefineFunction("Move(dist)", MoveTurtle);

   auto t = uc.ExpressionTransformer();
   t.FromTo("FD {@Number:dist}", "Move({dist})");
   t.FromTo("RT {@Number:deg}", "angle = angle - {deg}");
   t.FromTo("PD", "pen_down = true");

   // --- Script ---
   auto script = R"(
PD
FD 100
RT 90
FD 50
)";

   uc.EvalStr(script);

   cout << "Final Position: (" << uc.Eval("x") << ", " << uc.Eval("y") << ")" << endl;
}