using Godot;


namespace Rokojori
{  
  public class NetTransform: NetClassDefinition
  {
    public readonly NetVector3 position    = new NetVector3( Vector3.Zero );
    public readonly NetQuaternion rotation = new NetQuaternion( Quaternion.Identity );
    public readonly NetVector3 scale       = new NetVector3( Vector3.One );

    public NetTransform()
    {
      SetMembers( position, rotation, scale );
    }    
  }

  public class NetMovementData: NetClassDefinition
  {
    public readonly NetClass<NetTransform> transform = new NetClass<NetTransform>(
      new NetTransform()
    );

    public readonly NetInt id = new NetInt( -1 );

    public NetMovementData()
    {
      SetMembers( transform, id );
    }


  }

  [GlobalClass]
  public partial class BitViewTest : Action
  {
    protected override void _OnTrigger()
    {
      TestSingleBitWriting();
      TestByteWriting();
      TestIntVL8Writing();
      TestClassWriting();
    }

    public void TestSingleBitWriting()
    {
      RJLog.Log( "----- TestSingleBitWriting -------" );

      var bitView = BitView.CreateEmpty();
      var numBits = 21;

      for ( int i = 0; i < numBits; i++ )
      {
        bitView.WriteBit( i % 2 == 0 );       
      }

      LogAndTestReversal( bitView );
    }    

    public void TestClassWriting()
    {
      RJLog.Log( "----- TestClassWriting -------" );

      var bitView = BitView.CreateEmpty();
      bitView.WriteBit( true );
      bitView.WriteFloat( -1234.567f );

      var trsf = new NetTransform();
      trsf.position.value = new Vector3( 1, 2, 3 );
      trsf.rotation.value = Quaternion.FromEuler( new Vector3( 0, 90, 0 ) );
      trsf.scale.value = new Vector3( 10,5,-1 );
      //var md = new NetMovementData();

      trsf.WriteMembers( bitView );

      LogAndTestReversal( bitView );
      
      var copy = bitView.Clone();
      copy.SetPointer( 0 );

      var bit  = copy.ReadBit();
      var data = copy.ReadFloat();
      var copyTrsf = Singleton<NetClassDataType<NetTransform>>.Get().ReadData( copy );

      RJLog.Log( bit, data, trsf.position.value, trsf.rotation.value, trsf.scale.value );
      
    }  

    public void TestByteWriting()
    {
      RJLog.Log( "----- TestByteWriting -------" );

      var bitView = BitView.CreateEmpty();

      bitView.WriteByte( 1 );
      bitView.WriteByte( 0 );
      bitView.WriteByte( 0 );
      bitView.WriteByte( 0 );

      bitView.WriteBit( true );
      bitView.WriteBit( false );
      bitView.WriteBit( true );
      bitView.WriteByte( 19 );
      bitView.WriteByte( 84 );

      LogAndTestReversal( bitView );
    }

     public void TestIntVL8Writing()
    {
      RJLog.Log( "----- TestIntVL8Writing -------" );

      var bitView = BitView.CreateEmpty();

      bitView.WriteUIntVL8( 127 );
      bitView.WriteUIntVL8( 128 );
      bitView.WriteUIntVL8( 70000 );
      bitView.WriteUIntVL8( 17121984 );

      LogAndTestReversal( bitView );

      var copy = BitView.From( bitView.GetBytes(), bitView.numBits );      
      copy.SetPointer( 0 );
      
      RJLog.Log( "----- Reading -------" );

      for ( int i = 0; i < 4; i++ )
      {
        copy.ReadUIntVL8();
      }
    }


    void LogAndTestReversal( BitView bitView )
    {
      Log( bitView );
      
      var fromBytes = BitView.From( bitView.GetBytes(), bitView.numBits );

      Log( fromBytes );
    }

    void Log( BitView view )
    {
      RJLog.Log( view.GetBitString(), "|", ByteView.Stringify( view.GetBytes() ) );
    }
  }
}