using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Rfc1006Lib;

namespace CsRfc1006Demo
{
  public partial class Form1 : Form
  {
    Rfc1006 Rfc = new Rfc1006 ();
    string m_sIPAdr;
    byte[] m_SrcTSAP = new byte[256];
    uint m_uSrcTSAPLen;
    byte[] m_DstTSAP = new byte[256];
    uint m_uDstTSAPLen;
    uint m_uPort;
    uint m_uConnectTimeout;
    uint m_uRxTimeout;
    uint m_uTxTimeout;
    bool m_bStartAsServer;
    int m_Err;
    volatile bool m_bConnected;
    bool m_bOpened;
    bool m_bUseFastAck;

    public Form1()
    {
      InitializeComponent();
      m_bConnected = false;
      m_bOpened = false;
      m_Err = 0;
      StatusTimer.Start();
    }

    private bool CheckForm ()
    {
      int i;
      if (IPAddress.Text.Length == 0)
      {
        MessageBox.Show("Bitte IP-Adresse eingeben. / Please enter ip address.", this.Text);
        return (false);
      }
      if (Port.Text.Length == 0)
      {
        MessageBox.Show("Bitte Port eingeben. / Please enter Port.", this.Text);
        return (false);
      }

      m_sIPAdr = IPAddress.Text;
      for (i = 0 ; i < SrcTSAP.TextLength; i++)
        m_SrcTSAP[i] = (byte)SrcTSAP.Text[i];
      m_uSrcTSAPLen = (uint) i;

      for (i = 0; i < DstTSAP.TextLength; i++)
        m_DstTSAP[i] = (byte)DstTSAP.Text[i];
      m_uDstTSAPLen = (uint)i;

      m_uPort = uint.Parse(Port.Text);
      m_uConnectTimeout = uint.Parse(ConnectTimeout.Text);
      m_uRxTimeout = uint.Parse(RxTimeout.Text);
      m_uTxTimeout = uint.Parse(TxTimeout.Text);
      m_bStartAsServer = StartAsServer.Checked;
      m_bUseFastAck = UseFastAck.Checked;
      return (true);
    }

    private void ShowConnectStatus()
    {
      if (m_bConnected)
      {
        ConnectStatus.Text = "verbunden / connected";
        ConnectStatus.BackColor = Color.LightGreen;
      }
      else
      {
        ConnectStatus.Text = "nicht verbunden / not connected";
        ConnectStatus.BackColor = Color.LightPink;
      }
    }

    private void SetbOpened(bool bOpened)
    {
      m_bConnected = false;
      m_bOpened =
      btnClose.Enabled =
      btnConnect.Enabled = 
      btnGetStatus.Enabled =
      btnTxData.Enabled = 
      btnRxData.Enabled =  bOpened;


      IPAddress.Enabled =
      Port.Enabled =
      SrcTSAP.Enabled =
      DstTSAP.Enabled =
      ConnectTimeout.Enabled =
      TxTimeout.Enabled =
      StartAsServer.Enabled =
      btnOpen.Enabled =
      IPAddress.Enabled =!bOpened;
      SetbConnected(false);
    }

    private void SetbConnected(bool bConnected)
    {
      m_bConnected =bConnected;
      btnConnect.Enabled = !bConnected;
      ShowConnectStatus();
    }

    private void btnOpen_Click(object sender, EventArgs e)
    {
      int lRef;

      if (CheckForm())
      {
        if (m_bStartAsServer)
        {
          lRef = Rfc.OpenServer(m_sIPAdr, m_SrcTSAP, m_uSrcTSAPLen, m_DstTSAP, m_uDstTSAPLen);
          if (lRef < 0)
          {
            m_Err = lRef;
          }
          else
          {
            Rfc.StartServer(m_uPort, "", 16); // accept all IP Addesses, 16 connections
            m_Err = 0;
          }
        }
        else
        {
          lRef = Rfc.Open(m_sIPAdr, m_SrcTSAP, m_uSrcTSAPLen, m_DstTSAP, m_uDstTSAPLen, m_uPort, m_uConnectTimeout);
          if (lRef < 0)
          {
            m_Err = lRef;
          }
          else
          {
            Rfc.SetFastAck (m_bUseFastAck);
            m_Err = 0;
          }
        }

        SetbOpened(m_Err == 0);
      }
    }

    private void Form1_Load(object sender, EventArgs e)
    {
    }

    private void btnClose_Click(object sender, EventArgs e)
    {
      m_Err = Rfc.Close();
      SetbOpened(false);
      ShowStatus();
    }
    private String GetResultString(int Err)
    {
      int SocketErr;
      String S;

      switch (Err)
      {
        case Rfc1006.Result.E_NOERR:
          S = "Aktion erfolgreich. / Action was successfull!";
          break;

        case Rfc1006.Result.E_TIMEOUT:
          S = "Zeitüberlauf! / Timeout!";
          break;

        case Rfc1006.Result.E_NORES_AVAIL:
          S = "keine Resourcen mehr frei. / No more resources available.";
          break;

        case Rfc1006.Result.E_REF_NOTOPENED:
          S = "Mit der angegebenen Ref-Nr. wurde kein Rfc1006Openxxx aufgerufen. /"+ 
              "Passed RefNo wasn't init with call to Rfc1006Openxxx";
          break;

        case Rfc1006.Result.E_GENERAL:
          S = "allgemeiner Fehler / general error";
          break;

        case Rfc1006.Result.E_NOPARTNER:
          SocketErr = Rfc.GetSockErr ();
          S = string.Format("Partner nicht gefunden. / Can't find partner. SocketError:{0:D}", SocketErr);
          break;

        case Rfc1006.Result.E_SOCKERR:
          SocketErr = Rfc.GetSockErr();
          S = string.Format("Socketfehler Nr: {0:D} aufgetreten. / Socket error no:{1:D} occurred!", SocketErr, SocketErr);
          m_bConnected = false;
          break;

        case Rfc1006.Result.E_SERVER_YET_RUNNING:
          S = "Server ist bereits gestartet. / Server is running yet.";
          break;

        case Rfc1006.Result.E_STARTING_SERVER:
          S = "Server kann nicht gestartet werden. / Server couldn't be started.";
          break;

        case Rfc1006.Result.E_SERVER_NOT_RUNNING:
          S = "Server war nicht gestartet. / Server was not running.";
          break;

        case Rfc1006.Result.E_NOCONNECTION:
          S = "Noch kein Client mit Server verbunden. / No client yet connected to server.";
          break;

        case Rfc1006.Result.E_BUFSIZE:
          S = "Übergebender Empfangspuffer ist zu klein. / The buffer you passed is to small.";
          break;

        case Rfc1006.Result.E_PC_BUFSIZE:
          S = "Das übergebene Array hat zuwenig Elemente. / The Array you passed is to small.";
          break;

        case Rfc1006.Result.E_BADREF:
          S = "Referenz der Verbindung ist ungültig. / Reference of connection is invalid.";
          break;

        case Rfc1006.Result.E_ALREADY_OPENED:
          S = "Die Open-Funktion wurde bereits aufgerufen. / The Open was called already.";
          break;

        case Rfc1006.Result.E_DEMOOVER:
          S = "Demozeit ist abgelaufen (neu starten). / The demo period has expired (restart).";
          break;

        default:
          S = string.Format("Unbekannter Fehler aufgetreten. / Unknown error occured! (Nummer/Number: {0:d})", Err);
          break;
      }
      return (S);
    }

    private void ShowStatus()
    {
      String S = GetResultString(m_Err);
      Status.Text = S;
      if (m_Err != 0)
        Status.BackColor = Color.LightPink;
      else
        Status.BackColor = Color.LightGreen;
    }

    private void btnConnect_Click(object sender, EventArgs e)
    {
      if (!m_bConnected)
      {
        int Res;
        Res = Rfc.Connect();
        SetbConnected(Res == 1?true:false);
        if (Res <= 0)
          m_Err = Rfc1006.Result.E_SOCKERR;
        else
          m_Err = 0;
        ShowStatus();
      }
    }

    private void btnGetStatus_Click(object sender, EventArgs e)
    {
      bool bConnect;
      if (Rfc.GetStatus() == 1)
        bConnect = true;
      else
        bConnect = false;
      SetbConnected(bConnect);
    }

    private void btnTxData_Click(object sender, EventArgs e)
    {
      int Len;
      byte[] TxData = new byte [DataToSend.TextLength];
      for (Len = 0; Len < DataToSend.TextLength; Len++)
      {
        TxData[Len] = (byte) DataToSend.Text[Len];
      }
	    m_Err = Rfc.Tx (TxData, (uint) Len, m_uTxTimeout);
      if (m_Err >= 0)
        m_Err = 0;
      ShowStatus ();
    }

    private int DoRxData(uint RxTimeout)
    {
      int Len;
      byte[] RxData = new byte[2048];

      Len = Rfc.Rx (RxData, 2048, RxTimeout);

      m_Err = Len;
      if (Len > 0)
      {
        int i;
        m_Err = 0;
        string RxStr;
        RxStr = "";
        for (i = 0; i < Len; i++)
        {
          RxStr +=  (char) RxData[i];
        }
        DataReceived.Text = RxStr;
      }
      return (Len);
    }

    private void btnRxData_Click(object sender, EventArgs e)
    {
      m_Err = DoRxData(m_uRxTimeout);
      if (m_Err >= 0)
        m_Err = 0;
      ShowStatus();
    }


    private void StatusTimer_Tick(object sender, EventArgs e)
    {
      int Res;
      if (m_bConnected)
      {
        Res = DoRxData(50);
        if (Res < -1) // kleiner Timeout
        {
          bool bConnect;
          if (Rfc.GetStatus() == 1)
            bConnect = true;
          else
            bConnect = false;
          SetbConnected(bConnect);
        }
      }
      else 
      {
        bool bConnect;
        if (Rfc.GetStatus() == 1)
          bConnect = true;
        else
          bConnect = false;
        SetbConnected(bConnect);
      }
    }
  }
}


