using System;
using System.IO;

namespace bigloo 
{    
  public sealed class input_console_port: input_port 
  {
    private Stream _in= Console.OpenStandardInput();

    public input_console_port( int  size )
      : base( "[stdin]", size ) 
    {
    }

    public override void close() 
    {
    }

    public override bool rgc_charready() 
    {
      try
      {
        return (   ((forward+1) < abufsiz)
                || (_in.Position < _in.Length));
      }
      catch (Exception)
      {
        return false;
      }
    }

    public override bool reset_eof()
    {
      eof= false;
      reset_console();
      //clearerr();
      return true;
    }

    public void reset_console()
    {
      matchstart= 0;
      matchstop= 0;
      abufsiz= 1;
      buffer[0]= (byte)'\0';
      lastchar= (byte)'\n';
    }
    
    public override bool rgc_fill_buffer() 
    {
      int          bufsize= this.bufsiz;
      int          abufsize= this.abufsiz;
      int          matchstart= this.matchstart;

      // if the buffer is not full, we fill it 
      if (abufsize < bufsize)
        return rgc_size_fill_con_buffer( abufsize, bufsize-abufsize );

      if (0 < matchstart) 
      {
        // we shift the buffer left and we fill the buffer 
        byte[]     buffer= this.buffer;
        int        movesize= abufsize-matchstart;

        for ( int i= 0 ; i < movesize ; ++i )
          buffer[i]= buffer[matchstart+i];
        abufsize-= matchstart;
        this.matchstart= 0;
        this.matchstop-= matchstart;
        this.forward-= matchstart;
        this.lastchar= (byte)buffer[matchstart-1];

        return rgc_size_fill_con_buffer( abufsize, bufsize-abufsize );
      }

      // we current token is too large for the buffer 
      // we have to enlarge it.                       
      rgc_double_buffer();
      return rgc_fill_buffer();
    }

    bool rgc_size_fill_con_buffer( int  abufsize,
                                   int  size )
    {
      byte[]       buffer= this.buffer;

      --abufsize;
      while (0 < size)
      {
        int        ch= _in.ReadByte();

        if (ch == -1) 
        {
          eof= true;
          break;
        }
        buffer[abufsize++]= (byte)ch;
        --size;
        if (ch == '\n')
          break;
      }
      buffer[abufsize++]= (byte)'\0';
      this.abufsiz= abufsize;

      return (0 < this.abufsiz);
    }
  }
}
