
#ifndef CPPCLR_UTILS_H
#define CPPCLR_UTILS_H

#if !__cplusplus_cli 
#error Only for C++/CLI Applications (e.g. Visual Studio Windows Forms Projects)
#endif

#include <string>
// Simple functions to convert .NET String to std::string and vice versa. 
// They are sufficient for many applications, in particular for all examples
// in my textbooks (see www.rkaiser.de)
//   Richard Kaiser: C++ mit Visual Studio 2022 und Windows-Forms Anwendungen
//   Richard Kaiser: C++ mit Visual Studio 2019 und Windows-Forms Anwendungen
//   Richard Kaiser: C++ mit Visual Studio 2017 und Windows-Forms Anwendungen
//   Richard Kaiser: C++ mit Visual Studio 2008 und Windows-Forms Anwendungen
//
// See the examples in the function __test_converions() below.

namespace rk1 {

  // Conversion functions for .NET strings to std::string and vice versa in 
  // C++ Windows Forms projects (Visual Studio 2008 and later). 

  // The functions defined below 
  std::string to_string(System::String^ S);
  System::String^ to_String(std::string s);
  // can be used in the function __test_converions:

  void __test_converions() // only to illustrate the usage
  {
    using System::String; // This works only in a C++/CLI project, e.g. a C++ Windows 
                          // Forms application with Visual Studio 
    using std::string;
    char* c1 = "9ou9ouo";
    const char* c2 = "9ou9ouo";
    String^ SC1 = rk1::to_String(c1);
    String^ SC2 = rk1::to_String(c2);
    String^ SC3 = rk1::to_String("jjj");

    string s1 = "9ou9ouo";
    const string s2 = "9ou9ouo";
    String^ S1 = rk1::to_String(s1);
    String^ S2 = rk1::to_String(s2);
    String^ S3 = rk1::to_String("jojopj");

    string r1 = rk1::to_string(S1);
    string r2 = rk1::to_string(S2);
    string r3 = rk1::to_string("ikhhi");
  }

  std::string to_string(System::String^ S)
  {
    std::string s;
    for (int i = 0; i < S->Length; i++)
      s += S[i];
    return s;
  }

  System::String^ to_String(std::string s)
  {
    return gcnew System::String(s.c_str());
  }

  System::String^ to_String(const char* s)
  {
    return gcnew System::String(s);
  }

  System::String^ to_String(const wchar_t* s)
  {
    return gcnew System::String(s);
  }

  System::String^ to_String(std::wstring s)
  {
    return gcnew System::String(s.c_str());
  }


  // -------------------------------------------------------------
  ref class StaticTextBox // using "ref" defines a .NET (managed) class.
  { // Ermöglicht die Ausgabe in eine TextBox, ohne dass diese als
    // Parameter übergeben werden muss. 
    // Allows output to a TextBox without having to pass it as a
    // parameter.
    // 
    // Diese TextBox muss vor dem ersten Aufruf von WriteLine durch
    // einen Aufruf von Init festgelegt werden, z.B. im Konstruktor 
    // des Formulars.
    // This TextBox must be set before the first call of WriteLine by a 
    // call of Init, e.g.in the constructor of the form.

    static System::Windows::Forms::TextBox^ tb = nullptr;
  public:
    static void Init(System::Windows::Forms::TextBox^ tb_) 
    { 
      tb = tb_; 
    }

    static void WriteLine(std::string msg)
    {
      if (tb != nullptr)
        tb->AppendText(System::String::Format(rk1::to_String(msg) + "\r\n"));
      else
        System::Windows::Forms::MessageBox::Show(
          "StaticTextBox::texBox == nullptr (Init vergessen)");
    }

    /* Für diese Klasse können auch die folgenden Funktionen nützlich sein:
       The following functions can also be useful for this class:

    static void WriteLine(const char* msg)
    {
    if (tb != nullptr)
      tb->AppendText(String::Format(rk1::to_String(msg) + "\r\n"));
    }

    static void WriteLine(String^ format)
    {
      if (tb != nullptr)
        tb->AppendText(format + "\r\n");
      else
        MessageBox::Show("StaticTextBox::texBox == nullptr (Init vergessen)");
    }

    static void WriteLine(String^ format, Object^ arg0)
    {
      if (tb != nullptr)
        tb->AppendText(String::Format(format + "\r\n", arg0));
      else
        MessageBox::Show("StaticTextBox::texBox == nullptr (Init vergessen)");
    }

    static void WriteLine(String^ format, Object^ arg0, Object^ arg1)
    {
      if (tb != nullptr)
        tb->AppendText(String::Format(format + "\r\n", arg0, arg1));
      else
        MessageBox::Show("StaticTextBox::texBox == nullptr (Init vergessen)");
    }

    static void WriteLine(String^ format, Object^ arg0, Object^ arg1, Object^ arg2)
    {
      if (tb != nullptr)
        tb->AppendText(String::Format(format + "\r\n", arg0, arg1, arg2));
      else
        MessageBox::Show("StaticTextBox::texBox == nullptr (Init vergessen)");
    }
    */
  };

  void test_StaticTextBox(System::Windows::Forms::TextBox^ tb)
  {
    rk1::StaticTextBox::Init(tb);
    // StaticTextBox kann ähnlich wie System::Console verwendet werden:
    // StaticTextBox can be used similarly to System::Console:
    // using namespace System::Console;
    /*
    System::Console::WriteLine("Hallo");
    System::Console::WriteLine("Hallo 1={0}",1);
    System::Console::WriteLine("Hallo 1={0} 2={1}",1,2);
    System::Console::WriteLine("Hallo  1={0} 2={1} 3={2}",1,2,3);
    */
    rk1::StaticTextBox::WriteLine("Hallo");
    /*
    rk1::StaticTextBox::WriteLine("Hallo 1={0}", 1);
    rk1::StaticTextBox::WriteLine("Hallo 1={0} 2={1}", 1, 2);
    rk1::StaticTextBox::WriteLine("Hallo 1={0} 2={1} 3={2}", 1, 2, 3);
    */
  }
} // end of namespace rk1

#endif // !CPPCLR_UTILS_H
