// ************* input from Windows *******************************************
class tWindows
  { private:
      bool InPiece;
      int  NPieces;
      int  Piece[20];
      char AfterTab2[100];
      int  NAfterTab2;
      int  TabsSeen;

      void Connect();
      void Disconnect();
      void ProcessPieces();
      void ReadTime();
      void SendToAnnunciator();
      void SendToXBee();
      void SetTime();
      void StartDump();
      void Tickled();
    public:
      void Clear();
      void GetChars();
  }; // tWindows

void tWindows::Clear()
  { AfterTab2[0] = 0;
    InPiece      = false;
    NAfterTab2   = 0;
    NPieces      = 0;
    Piece[0]     = 0;
    TabsSeen     = 0;
  } // tWindows::Clear()

void tWindows::Connect()
  { if (Infrastructure.GlobalStatus != gsNotConnected)
      { Infrastructure.TellWindows(btwAlreadyConnected); }
    else
      { // make connection
        elmsSinceTickled = 0;
        Infrastructure.SetGlobalStatus(gsJustConnected);
        Infrastructure.TellWindows(btwConnected);
        ReadTime();
      } // make connection
  } // tWindows::Connect()

void tWindows::Disconnect()
  { if (Infrastructure.ConfirmNotDumping("disconnect"))
      { // allowed
        Infrastructure.TellWindows(btwDisconnectedRQ);
        Infrastructure.SetGlobalStatus(gsNotConnected);
      } // allowed
  } // tWindows::Disconnect()

void tWindows::GetChars()
  { // called from main loop, when at least one char is available
    char C;

    while (WindowsSerial.available())
      { // get at least one character
        C = WindowsSerial.read();
        switch (C)
          { case    '\n':
            case EXCLAIM: ProcessPieces();
                          break;

            case  BLANK: InPiece = false;
                         if (TabsSeen == 2)
                           { // save it
                             AfterTab2[NAfterTab2] = C;
                             NAfterTab2++;
                             AfterTab2[NAfterTab2] = 0;
                           } // save it
                         break;

            case    TAB: InPiece = false;
                         TabsSeen++;
                         break;

                default: if (not InPiece)
                           { Piece[NPieces] = 0;
                             NPieces++;
                             InPiece = true;
                           }
                         Piece[NPieces-1] = 10 * Piece[NPieces-1] + C - '0';
                         if (TabsSeen == 2)
                           { // save it
                             AfterTab2[NAfterTab2] = C;
                             NAfterTab2++;
                             AfterTab2[NAfterTab2] = 0;
                           } // save it
                         break;
          } // switch
      } // get at least one character
  } // tWindows::GetChars()

void tWindows::ProcessPieces()
  { Infrastructure.Interrupting = false;

    tWindowsToBase WTB = tWindowsToBase(Piece[0]);

    // char DebugMessage[100];
    // sprintf(DebugMessage, "W2.ProcessPieces: WTB = %d with %d total pieces", WTB, NPieces);
    // Infrastructure.TellWindows(DebugMessage, btwDebugging);

    switch (WTB)
      { case       wtbAnnunciator: SendToAnnunciator();                     break;
        case             wtbEMPTY:                                          break;
        case           wtbConnect: Connect();                               break;
        case        wtbDisconnect: Disconnect();                            break;
        case     wtbInitializeuSD: FileSystem.CleareduSDCard();             break;
        case          wtbReadTime: ReadTime();                              break;
        case        wtbSendToXBee: SendToXBee();                            break;
        case           wtbSetTime: SetTime();                               break;
        case          wtbShutDown: Infrastructure.ShutDownRequested = true; break;
        case         wtbStartDump: StartDump();                             break;
        case wtbTickleBaseStation: Tickled();                               break;
                          default:                                          break;
      } // switch on WindowsAppRQ

    Clear();
  } // tWindows::ProcessPieces()

void tWindows::ReadTime()
  { // routine ID 7040
    // send time from DS1307 to Windows
    char Message[50];
    DS1307.ReadDS1307();
    sprintf(Message, "RTC\t%s", DS1307.LatestTimestamp);
    Infrastructure.TellWindows(Message, btwReadTime);
  } // tWindows::ReadTime()


void tWindows::SendToAnnunciator()
  { //   NPieces       1               2           3     
    //   index         0               1           2
    // call is wtbSendToAnnunciator  XBeeID       Text
    // parse is useless, since it treats blanks as separators and handles only
    //   integers
    // char DebugMessage[100];

    if (Infrastructure.ConfirmNotDumping("send to Annunciator") and (NPieces >= 3))
      { // allowed
        // sprintf(DebugMessage, "in Windows.SendToAnnuncoiator with '%s' for %d", AfterTab2, Piece[1]);
        // Infrastructure.TellWindows(DebugMessage, btwDebugging);
        if (not XBee.Transmit(Piece[1], AfterTab2))
          { Infrastructure.BadNews("failed trx to XBee", btwFailedTransmission); }
      } // allowed
  } //  tWindows::SendToAnnunciator()

void tWindows::SendToXBee()
  { //       NPieces   1            2               3               4           5         6     7       8
    //       index     0            1               2               3           4         5     6       7
    // max call is wtbSendToXBee  XBeeID      wtbRelayRunOnce    on time       off time
    // sample #1   wtbSendToXBee  XBeeID        wtbTargetF       <target>    <10 * hysteresis>
    //                14           205             19             55            10
    // sample #2 wtbSendToXBee    XBeeID  wtbBroadcastLocalTime   <year>      <month>   <day> <hour> <minute>
    //                14           205             26              2023         7         2     12      17
    char Payload[100];
    char DebugMessage[50];

    if (Infrastructure.ConfirmNotDumping("send to XBee") and (NPieces >= 2))
      { // allowed
        switch (NPieces)
          { case  3: sprintf(Payload, "%d",         Piece[2]);
                     sprintf(DebugMessage, "W.SendToXBee(%d, %d)",
                                           Piece[1], Piece[2]);
                     break;
            case  4: sprintf(Payload, "%d\t%d",     Piece[2], Piece[3]);
                     sprintf(DebugMessage, "W.SendToXBee(%d, %d-->%d)",
                                           Piece[1], Piece[2], Piece[3]);
                     break;
            case  5: sprintf(Payload, "%d\t%d\t%d", Piece[2], Piece[3], Piece[4]);
                     sprintf(DebugMessage, "W.SendToXBee(%d, %d-->%d-->%d)",
                                           Piece[1], Piece[2], Piece[3], Piece[4]);
                     break;
                     //                wtb Y   M   D   H   M
            case  8: sprintf(Payload, "%d\t%d\t%d\t%d\t%d\t%d",
                                      Piece[2], Piece[3], Piece[4],
                                      Piece[5], Piece[6], Piece[7]);
            default: break;
          } // switch

        Infrastructure.TellWindows(DebugMessage, btwDebugging);
        if (not XBee.Transmit(Piece[1], Payload))
          { Infrastructure.BadNews("failed trx to XBee", btwFailedTransmission); }
      } // allowed
  } // tWindows::SendToXBee

void tWindows::SetTime()
  { if (Infrastructure.ConfirmNotDumping("set time"))
      { // allowed
        // Infrastructure.TellWindows("actually setting it", btwDebugging);

        DS1307.SetDS1307(Piece[1],  // year
                         Piece[2],  // month
                         Piece[3],  // day
                         Piece[4],  // hour
                         Piece[5],  // minute
                         Piece[6]); // second
      } // allowed
  } // tWindows::SetTime

void tWindows::StartDump()
  { if (GrossDumpSize > 0)
      { FileSystem.StartDump(); }
  } // tWindows::StartDump()

void tWindows::Tickled()
  { elmsSinceTickled = 0;
    Infrastructure.TellWindows(btwNotDeadYet);
  } // tWindows::Tickled()


