#!/usr/bin/env python
# stream.py : A simple streamer
# [2012.01.31] Mendez

# [System]
import re

from clint.textui import puts, colored, progress
from pygrbl import argv
from pygrbl.communicate import Communicate
from pygrbl.util import deltaTime

DESC = 'Simple python GRBL streamer'
RX_BUFFER_SIZE = 128


def stream(args, serial, lines):
  '''keep track of all '''
  inBuf = [] # array of length of lines in buffer
  for i,line in enumerate(progress.bar(lines)):
    # Strip comments/spaces/new line, capitalize, and add line ending
    l = re.sub('\s|\(.*?\)','',line.strip()).upper()+'\n'  

    # if this was a comment or blank line just go to the next one
    if len(l.strip()) == 0:
      continue
  
    out = ''
    # if the serial is has text and we have not filled the buffer
    while sum(inBuf) >= RX_BUFFER_SIZE-1 | serial.inWaiting():
      tmp = serial.readline().strip()

      # allows you to debug without a serial connection
      if args.debug:
        out='DEBUG'
        inBuf.pop(0)
        break

      # recieved an ok == ready to send a new command
      if 'ok' in tmp:
        out += tmp
        inBuf.pop(0)
      else:
        # this could be an error or something that is not good.
        if len(tmp) > 0:
          puts(colored.red('\n DEBUG: %s\n'%(tmp)))
      
  
    #  send the command
    serial.write(l)
    inBuf.append(len(l))
    if not args.quiet:
      puts(colored.blue('[%04d][Sent: %s][Buf:%3d]'%(i,l.strip().rjust(30),sum(inBuf))) +
           colored.green(' Rec: %s'%(out))+' '*12)

  
  
  



if __name__ == '__main__':
  # Initialize the args
  args = argv.arg(description='', getFile=True)

  # Let go!
  start = util.deltaTime()
  puts(colored.blue(' Starting file: %s \n at %s'%(args.gcode.name, start)))

  # read the full file and then close so that it cannot change.
  # I am pretty sure even at 1M lines, I should be able to hold this in mem
  lines = args.gcode.readlines()
  args.gcode.close()

  # get a serial device and wake up the grbl, by sending it some enters
  with Communicate(args.device, args.speed, timeout=args.timeout,
                   debug=args.debug,
                   quiet=args.quiet) as serial:
    
    # seperate this out for clarity
    _stream(args, serial, lines)
    
    # It seems everything is ok, but dont reset everything untill buffer completes
    puts(colored.green('\n gCode finished streaming!'))
    puts(colored.green('\n        RunTime: {}'.format(deltaTime(start))))
    puts(colored.red(  '\n    !!! WARNING: Please make sure that the buffer clears before finishing...') )
    raw_input(' <Press any key to finish>')
    raw_input('   Are you sure? Any key to REALLY exit.')
    