import gcode_write

import move

import move_parms
import rn

from math import sqrt, sin, cos, floor, ceil, pi, inf, nan

def write_slice(fname, moves_list, test_parms, parms): 
  wr = open(fname, 'a')
  
  islice = test_parms['islice']
  zslice = test_parms['Z']
  zspeed = parms['job_z_speed']
  zstep = parms['slice_thickness']
  fdiam = parms['filament_diameter']

  slice_preamble(wr, islice, zslice, zspeed)

  last_jump_q, last_jump_mp = None, None
  contour_id = 1
  raster_id = 1

  for moves in moves_list:
    if len(moves) == 1 and move.is_jump(moves[0]):
      last_jump_mp = move.parameters(moves[0])
      last_jump_q = move.pfin(moves[0])

    else:
      pini = move.pini(moves[0])
      pfin = move.pfin(moves[-1])
      
      wr.write("\n") 

      if pini == pfin:
        wr.write('(Offset ' + str(contour_id) + ')\n')
        contour_id += 1
        ### ???

      else:
        wr.write('(Raster ' + str(raster_id) + ')\n')
        raster_id += 1

      jump(wr, last_jump_q, last_jump_mp)
      last_jump_q, last_jump_mp = None, None

      for mv in moves:
        mpk = move.parameters(mv)
        p, q = move.endpoints(mv)
        trace(wr, p, q, mpk, zstep, fdiam)

  slice_postamble(wr, islice)

  return

############
def file_preamble(wr, ex_temp):

  wr.write("M104 S%.0f ; set temperature, no wait\n" % ex_temp)
  wr.write("M107 ; print cooling fan off\n")
  wr.write("G21 ; set units to millimeters\n")
  wr.write("G28 ; move to home position\n")
  wr.write("G92 X0 Y0 E0 ; set coordinate origin\n")
  wr.write("G90 ; use absolute coordinates\n")
  wr.write("M83 ; use relative coordinates for the filament\n")
  wr.write("M109 S%.0f ; wait for temperature\n" % ex_temp)

  # Extrude 20 mm of filament at 100 mm/min without moving, to prime the nozzle:
  wr.write("G1 E20.0 F100.0 ; extrude\n")
  wr.write("G1 EPOS-2.00000 F24000 ; retract filament\n")
  wr.write("\n") 
  wr.flush()
  return
  # ----------------------------------------------------------------------

def file_postamble(wr):
  wr.write("M107 ; print cooling fan off\n")
  wr.write("M104 S0 ; nozzle heater off\n")
  wr.write("G28 ; home all axes\n")
  wr.flush()
  return
  # ----------------------------------------------------------------------

def slice_preamble(wr, islice, zslice, zspeed):
  wr.write("(begin layer %d)\n" % islice)
  zex = zslice # Z cordinate of nozzle while extruding.
  # G-code speeds are in mm/min not mm/s
  wr.write("G1 Z%.3f F%.0f ; move to layer's Z" % (zex, 60*zspeed))
  wr.write("\n") 

def slice_postamble(wr, islice):
  # Writes the G-code to finalize the current slice.
  wr.write("\n") 
  wr.write("(end layer %d)" % islice)
  wr.flush()

############
def jump(wr, q, mp):
  ac, sp, ud = move_parms.dynamics(mp)
  # Speed in G-code is mm/min not mm/s
  wr.write("G1 E-2 F2400\n")
  wr.write("G1 E0 X%.6f Y%.6f F%d\n" % (q[0], q[1], 60*sp))
  wr.write("G1 E2 F2400\n")

def trace(wr, p, q, mp, zstep, fdiam):
  wd = move_parms.width(mp)
  ac, sp, ud = move_parms.dynamics(mp)
  tfeed = compute_feed_length(p, q, wd, zstep, fdiam)
  # Speed in G-code is mm/min not mm/s
  wr.write("G1 X%.6f Y%.6f E%.3f F%d\n" % (q[0], q[1], tfeed, 60*sp))

def compute_feed_length(p, q, wd, zstep, fdiam):
  dpq = rn.dist(p, q)

  # Compute area {tarea} of cross-section of extruded material, assuming that it is 
  # a rectangle with height {zstep} and width {wdt-zstep} with semicircles
  # of radius {zstep/2} on each side:
  tarea = zstep * wd

  volume = dpq*tarea # Volume of material needed
  
  # Compute area of cross-section of filament:
  farea = pi*fdiam*fdiam/4
  
  # Length of filament
  flength = volume/farea

  return flength
