#property strict
#property indicator_chart_window
#property indicator_plots 0

input string InpChannel = "O8_56";
input int    InpStaleAfterSec = 30;
input int    InpTimerSec = 1;

string g_prefix, g_panel;
long g_chart_id;
datetime g_last_local = 0;
string g_last_event = "NONE";

string Key(const string suffix)
  { return g_prefix + "." + suffix; }

void Publish(const string event_name)
  {
   const datetime now = TimeLocal();
   g_last_local = now;
   g_last_event = event_name;
   GlobalVariableSet(Key("id"), (double)g_chart_id);
   GlobalVariableSet(Key("time"), (double)now);
   GlobalVariableSet(Key("event"), (double)EventCodeFromName(event_name));
  }

string EventName(const int id)
  {
   if(id==CHARTEVENT_CLICK) return "CLICK";
   if(id==CHARTEVENT_OBJECT_CLICK) return "OBJECT_CLICK";
   if(id==CHARTEVENT_KEYDOWN) return "KEYDOWN";
   if(id==CHARTEVENT_KEYUP) return "KEYUP";
   if(id==CHARTEVENT_MOUSE_WHEEL) return "MOUSE_WHEEL";
   return "EVENT";
  }

int EventCodeFromName(const string name)
  {
   if(name=="CLICK") return 1;
   if(name=="OBJECT_CLICK") return 2;
   if(name=="KEYDOWN") return 3;
   if(name=="KEYUP") return 4;
   if(name=="MOUSE_WHEEL") return 5;
   return 0;
  }

string EventFromCode(const int code)
  {
   if(code==1) return "CLICK";
   if(code==2) return "OBJECT_CLICK";
   if(code==3) return "KEYDOWN";
   if(code==4) return "KEYUP";
   if(code==5) return "MOUSE_WHEEL";
   return "EVENT";
  }

void Render()
  {
   const datetime now = TimeLocal();
   long last_id = 0;
   datetime last_time = 0;
   int last_event_code = 0;
   if(GlobalVariableCheck(Key("id"))) last_id = (long)GlobalVariableGet(Key("id"));
   if(GlobalVariableCheck(Key("time"))) last_time = (datetime)GlobalVariableGet(Key("time"));
   if(GlobalVariableCheck(Key("event"))) last_event_code = (int)GlobalVariableGet(Key("event"));
   const int age = (last_time>0 && now>=last_time) ? (int)(now-last_time) : -1;
   const bool fresh = (age>=0 && age<=InpStaleAfterSec);
   string status = fresh ? "RECENT" : "UNKNOWN / STALE";
   string text = "SEMANTICS: LAST INTERACTION (NOT ACTIVE TAB)\n";
   text += "STATUS: " + status + "\n";
   text += "LAST CHART ID: " + (fresh ? IntegerToString(last_id) : "-") + "\n";
   text += "THIS CHART: " + IntegerToString(g_chart_id) + "\n";
   text += "AGE: " + (fresh ? IntegerToString(age)+" sec" : "-") + "\n";
   text += "LAST EVENT: " + (fresh ? EventFromCode(last_event_code) : "-") + "\n";
   text += "LOCAL EVENT: " + g_last_event;
   Comment(text);
  }

int OnInit()
  {
   g_chart_id = ChartID();
   g_prefix = "O8_56_" + InpChannel;
   EventSetTimer(MathMax(1, InpTimerSec));
   Render();
   return INIT_SUCCEEDED;
  }

void OnDeinit(const int reason)
  { EventKillTimer(); Comment(""); }

void OnTimer()
  { Render(); }

void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
  {
   if(id==CHARTEVENT_CLICK || id==CHARTEVENT_OBJECT_CLICK || id==CHARTEVENT_KEYDOWN ||
      id==CHARTEVENT_KEYUP || id==CHARTEVENT_MOUSE_WHEEL)
     {
      Publish(EventName(id));
      Render();
     }
  }

int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[],
                const double &open[], const double &high[], const double &low[],
                const double &close[], const long &tick_volume[], const long &volume[],
                const int &spread[])
  { return rates_total; }
