#!/usr/bin/python -tt
# -*- coding: utf-8 -*-

#Marc Cobler Cosmen - June 2016
#Released under MIT LICENSE
#https://opensource.org/licenses/MIT


"""A tiny Python program to modify some parameters on Gcodes
generated by Slic3r or similar.
The main objective is to modify 3D printer Gcode to be able to print with larger
printers controlled by MACH3 and with a VFD driving a pump
"""

import sys
import os
import re
from glob import glob
from fileHandler import *

#-------------------VARIABLES--------------------
#layers is a list containing the line numbers of the layer changes
layers = []
#indexes is a list of lists containing the line number and the index of the matching axis to delete for each line
# indexes = [[line0, index0], [line1, index1]...]
indexes = []
#travels is a list of the line numbers containing travels
travels = []
#file input valid formats
formats =[".gcode", ".txt"]

commentFileExtension = '_withoutComments'
preparedFileExtension = '_prepared'

def parseFile(file):
    print ('Reading the entire file...')
    lines = 0
    travel = 0
    f = open(file)
    for line in f:
        #Search for travel movements in the file
        #Scan travel speed and make it variable in the search
        travelMatch = re.search(r'G1 X\d+.\d+ Y\d+.\d+ F7200.\d+', line, )
        if travelMatch:
            travel += 1
            travels.append(lines)

        #Search for the indexes of the A axis in each line
        axisMatch = re.search(r'A[0-9]*', line,)
        if axisMatch:
            #fill the indexes list
            index = [lines, axisMatch.start()]
            indexes.append(index)
            #print index
        #Search for layer changes
        layerMatch = re.search(r'[Z][0-9]*',line,)
        if layerMatch:
            layers.append(lines)
        else:
            pass
        lines += 1
    #Close the opened file
    f.close()
    print ('There are {} lines in the file'.format(lines))
    print ('There are {} layers in the file'.format(len(layers)))
    print ('There are {} travels in the file'.format(travel))

def deleteComments(file, format = '.gcode'):
    """
    Deletes all the comments. In a G-code file usually comments start with ';'
    """
    print ('Removing all the comments...')
    newFileName = makeBlankFile(file, commentFileExtension, format)
    inputFile = open(file, 'r')
    outputFile = open(newFileName, 'w')
    for line in inputFile:
        commentMatch = re.search(r';*', line,)
        if commentMatch:
            newLine = re.sub(r';.*', '', line)
            outputFile.write(line.replace(line, newLine))
        else:
            outputFile.write(line)

    inputFile.close()
    outputFile.close()
    print ('Done!')

def removeAAxis(file, format = '.gcode'):
    """
    Removes A axis from the G-code line. this is useful when you have a machine that does not use a
    specified axis.
    """
    print ('Removing A Axis from the file...')
    #First let's see if the _withoutComments file exists in the current directory
    fileName = file[:file.find(".")] + commentFileExtension + format
    exists = findFileInDir(fileName)
    #let's create the preparedFileExtension file
    newFileName = makeBlankFile(file, preparedFileExtension, format)
    if exists:
        #if exist we have to read from it and delete it afterwards
        print ('File exist. Reading from it')
        inputFile = open(fileName, 'r') #only read
        outputFile = open(newFileName, 'w') #only write
    else:
        #the file doesn't exists. So we read from the original file
        print ('File does not exist. Reading from the original')
        inputFile = open(file, 'r')
        outputFile = open(newFileName, 'w')

    for line in inputFile:
        axisMatch = re.search(r'A[0-9]*', line,)
        if axisMatch:
            newLine = re.sub(r'A\d*.\d+', '', line)
            outputFile.write(line.replace(line, newLine))
        else:
            outputFile.write(line)

    inputFile.close()
    outputFile.close()
    if exists:
        #Remove the file we don't need
        os.remove(fileName)
    print ('Done!')



# Define a main() function that prints a little greeting.
def main():
    print ('\n --------Welcome to the G-code Modifier Utility--------- \n')
    #Get the arguments of the program and decide what to do
    if len(sys.argv) >= 2:
        fileExtension = getFileExtension(sys.argv[1])
        #the argument should be a .gcode file
        if fileExtension in formats:
            gcodeFile = sys.argv[1]
            if findFileInDir(gcodeFile):
                #file specified found in the directory
                print ('The file selected is: {}'.format(gcodeFile))
            else:
                print ('File not found in directory. Please try again.')
                quit()
        else:
            #There has been an Error
            print ('The file is not valid. Input files should be .gcode or .txt')
            print ('\n\n\n')
            quit()
    else:
        #We should print all the available .gcode files in the working directory
        print ('No input file detected. Here are the available .gcode files in ')
        print (os.getcwd() + ' : \n')
        filesInDir = glob('*.gcode')    #get all the gcodes in the directory
        for file in filesInDir:         #print them out in a 'list'
            print ('-> {}'.format(file))
        print ('\n')
        #Now we have to select the file we want to work with
        rawInput = str(input('Please type the g-code file you want to work with: '))
        if rawInput in filesInDir:
            #The input file is the list of files!
            gcodeFile = rawInput
            print ('The file selected is: {}'.format(gcodeFile))
        else:
            #There has been an Error
            print ('The file is not in the directory. Please verify and write it as it is.')
            print ('\n\n')
            main()

    #ask the user the output file format
    fileFormat = str(input('Type the output file format: '))
    if not fileFormat:      #check if it's empty
        print ('No file format specified, please try again')
        main()
    elif fileFormat == '.': #check if there's only a point
        print ('you missed the rest of the format! try again')
        main()
    elif not fileFormat.startswith('.'):
        print ('You missed the . !! I\'ll put it for you...')
        fileFormat = '.' + fileFormat
    else:
        pass

    #Open the file, get some data and print it out
    parseFile(gcodeFile)
    #Now let's start modifying the new gcode itself
    optionComments = str(input('Do you want to remove all the comments in the file? '))
    optionAxis = str(input('Do you want to remove A Axis from the G-code? '))
    if optionComments == 'y':
        deleteComments(gcodeFile, fileFormat)
        if optionAxis == 'y':
            removeAAxis(gcodeFile, fileFormat)
        elif optionAxis == 'n':
            pass
        else:
            print ('Type "y" for yes or "n" for no please')
            main()
    elif optionComments == 'n':
        pass
    else:
        print ('Type "y" for yes or "n" for no please')
        main()

# This is the standard boilerplate that calls the main() function.
if __name__ == '__main__':
    main()
