fs = require 'fs'
noflo = require 'noflo'
sw = require 'socketwatcher'

# @runtime noflo-nodejs
# https://github.com/ev3dev/ev3dev/wiki/Using-Sensors
# no poll support yet!
# https://github.com/ev3dev/ev3dev/issues/104

LOG_PREFIX = 'legoev3/TouchSensor2:'

class TouchSensor2 extends noflo.Component
  description: 'Detect touch events.'
  icon: 'power-off'

  constructor: ->
    console.log "#{LOG_PREFIX} creating new component"

    @watcher = new sw.SocketWatcher()
    @fd = null
    @running = false
    @last_value = null
    @updateBase 0

    @inPorts = new noflo.InPorts
      kick:
        datatype: 'bang'
        description: 'Probe the sensor'
      port:
        datatype: 'int'
        values: [0,1,2,3]
        description: 'Sensor port'

    @outPorts = new noflo.OutPorts
      value:
        datatype: 'boolean'
        description: 'Sends true, if touch sensor pressed'

    @inPorts.kick.on 'data', =>
      console.log "#{LOG_PREFIX} start (running=#{@running})"
      return if @running
      @running = true
      @outPorts.value.connect()
      console.log "#{LOG_PREFIX} start watching"
      @watch()
      console.log "#{LOG_PREFIX} watching ..."

    @inPorts.port.on 'data', (data) =>
      @updateBase data

    console.log "#{LOG_PREFIX} created new component"

  updateBase: (port) ->
    @unwatch() if @running
    @base = '/sys/class/msensor/sensor' + port + '/value0'
    @watch() if @running

  sensor: ->
    buf = new Buffer(1)
    fs.readSync @fd, buf, 0, buf.length, null
    new_value = parseInt buf.toString()
    console.log "#{LOG_PREFIX} event #{new_value}"
    if new_value isnt @last_value
      @last_value = new_value
      @outPorts.value.send (new_value is 1)

  watch: ->
    console.log "#{LOG_PREFIX} watches #{@base}"
    try
      @fd = fs.openSync @base, 'r'
      return unless @fd
      @watcher.callback = @sensor
      @watcher.set @fd, true, false
      @watcher.start()
    catch err
      console.log "#{LOG_PREFIX} open(#{@base}) failed: #{err}"

  unwatch: ->
    console.log "#{LOG_PREFIX} is idle"
    return unless @fd
    @watcher.stop()
    fs.closeSync @fd
    @fd = null

  shutdown: ->
    console.log "#{LOG_PREFIX} stop (running=#{@running})"
    return unless @running
    @unwatch()
    @running = false

exports.getComponent = -> new TouchSensor2()

