#!/usr/bin/env coffee
# CamanJS benchmarking script
# Benchmarks how fast each filter takes to render
{Caman} = require __dirname + "/../dist/caman.full"
cli     = require 'cli'
Table   = require 'cli-table'

cli.setUsage('bench [OPTIONS]')

# All of the filters to test
filters = [
  ['fillColor', ['#ff0000']]
  ['brightness', [50]]
  ['saturation', [50]]
  ['vibrance', [50]]
  ['greyscale', [50]]
  ['contrast', [10]]
  ['hue', [50]]
  ['colorize', ['#ff0000', 50]]
  ['invert', []]
  ['sepia', [50]]
  ['gamma', [1.5]]
  ['noise', [50]]
  ['clip', [50]]
  ['channels', [{red: 50, green: 20, blue: 10}]]
  ['curves', [['rgb'], [0, 0], [100, 100], [200, 200], [255, 255]]]
  ['exposure', [50]]
  ['boxBlur', []]
  ['radialBlur', []]
  ['heavyRadialBlur', []]
  ['gaussianBlur', []]
  ['motionBlur', []]
  ['sharpen', [50]]
]

cli.parse
  samples: ['s', 'Number of samples per filter', 'number', 3]
  image: ['i', 'Image to use in the tests', 'path', __dirname + '/../examples/images/test1_640.jpg']
  blocks: ['b', 'Number of blocks the renderer should use', 'number', require('os').cpus().length]

class Bench
  currentSample: 0
  times: {}
  tableData: []

  constructor: (@options) ->
    tableHead = ['Filter']
    for i in [0...@options.samples]
      tableHead.push "Sample #{i+1} (ms)"

    tableHead.push "Average (ms)"
    @table = new Table head: tableHead

    @getNextFilter()

  setInstance: (c) -> @c = c

  next: =>
    if @currentSample is @options.samples
      return @print() unless @getNextFilter()

    @currentSample++

    #console.log "#{@filterName} - Sample #{@currentSample}"
    @c.revert()
    @c[@filterName].apply(@c, @filterArgs)

    start = (new Date()).getTime()
    @c.render =>
      end = (new Date()).getTime()
      @times[@filterName] = [] unless @times[@filterName]
      @times[@filterName].push(end - start)
      @next()

  getNextFilter: ->
    return false if filters.length is 0

    @currentSample = 0
    [@filterName, @filterArgs] = filters.shift()
    console.log "Running filter: #{@filterName}"
    true

  print: ->
    for own filter, times of @times
      average = 0
      average += val for val in times
      average /= times.length
      average = Math.round(average * 1000) / 1000
      data = [filter].concat(times)
      data.push average
      @table.push data

    console.log "\nResults"
    console.log "NodeJS #{process.version}"
    console.log "Image: #{@options.image.split('/').pop()}"
    console.log "Size: #{@c.dimensions.width}x#{@c.dimensions.height} - #{@c.pixelData.length / 4} pixels"
    console.log "CPUs: #{require('os').cpus().length}"
    console.log "\n" + @table.toString()

# Start the program
cli.main (args, options) ->
  console.log """
  Running #{options.samples} samples for #{filters.length} filters.
  The renderer will use #{options.blocks} blocks.

  """

  Caman.Renderer.Blocks = options.blocks

  bench = new Bench(options)
  caman = Caman options.image, ->
    bench.setInstance caman
    bench.next()