// Generated by IcedCoffeeScript 1.7.1-f
(function() {
  var Generator, iced, __iced_k, __iced_k_noop;

  iced = require('iced-runtime');
  __iced_k = __iced_k_noop = function() {};

  Generator = Generator = (function() {
    function Generator(opts) {
      opts = opts || {};
      this.lazy_loop_delay = opts.lazy_loop_delay || 30;
      this.loop_delay = opts.loop_delay || 5;
      this.work_min = opts.work_min || 1;
      this.auto_stop_bits = opts.auto_stop_bits || 4096;
      this.max_bits_per_delta = opts.max_bits_per_delta || 4;
      this.auto_stop = opts.auto_stop ? opts.auto_stop : true;
      this.entropies = [];
      this.running = true;
      this.is_generating = false;
      this.timer_race_loop();
    }

    Generator.prototype.generate = function(bits_wanted, cb) {
      var e, harvested_bits, res, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      this.is_generating = true;
      if (!this.running) {
        this.resume();
      }
      harvested_bits = 0;
      res = [];
      (function(_this) {
        return (function(__iced_k) {
          var _results, _while;
          _results = [];
          _while = function(__iced_k) {
            var _break, _continue, _next;
            _break = function() {
              return __iced_k(_results);
            };
            _continue = function() {
              return iced.trampoline(function() {
                return _while(__iced_k);
              });
            };
            _next = function(__iced_next_arg) {
              _results.push(__iced_next_arg);
              return _continue();
            };
            if (!(harvested_bits < bits_wanted)) {
              return _break();
            } else {
              (function(__iced_k) {
                if (_this.entropies.length) {
                  e = _this.entropies.splice(0, 1)[0];
                  harvested_bits += e[1];
                  return __iced_k(res.push(e[0]));
                } else {
                  (function(__iced_k) {
                    __iced_deferrals = new iced.Deferrals(__iced_k, {
                      parent: ___iced_passed_deferral,
                      filename: "/Users/chris/git/more-entropy/src/generator.iced",
                      funcname: "Generator.generate"
                    });
                    _this.delay(__iced_deferrals.defer({
                      lineno: 28
                    }));
                    __iced_deferrals._fulfill();
                  })(__iced_k);
                }
              })(_next);
            }
          };
          _while(__iced_k);
        });
      })(this)((function(_this) {
        return function() {
          if (_this.auto_stop) {
            _this.stop();
          }
          _this.is_generating = false;
          return cb(res);
        };
      })(this));
    };

    Generator.prototype.stop = function() {
      return this.running = false;
    };

    Generator.prototype.resume = function() {
      this.running = true;
      return this.timer_race_loop();
    };

    Generator.prototype.reset = function() {
      this.entropies = [];
      return this.total_bits = 0;
    };

    Generator.prototype.count_unused_bits = function() {
      var bits, e, _i, _len, _ref;
      bits = 0;
      _ref = this.entropies;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        e = _ref[_i];
        bits += e[1];
      }
      return bits;
    };

    Generator.prototype.delay = function(cb) {
      var delay, ___iced_passed_deferral, __iced_deferrals, __iced_k;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      delay = this.is_generating ? this.loop_delay : this.lazy_loop_delay;
      (function(_this) {
        return (function(__iced_k) {
          __iced_deferrals = new iced.Deferrals(__iced_k, {
            parent: ___iced_passed_deferral,
            filename: "/Users/chris/git/more-entropy/src/generator.iced",
            funcname: "Generator.delay"
          });
          setTimeout(__iced_deferrals.defer({
            lineno: 50
          }), delay);
          __iced_deferrals._fulfill();
        });
      })(this)((function(_this) {
        return function() {
          return cb();
        };
      })(this));
    };

    Generator.prototype.timer_race_loop = function() {
      var ___iced_passed_deferral, __iced_k, _results, _while;
      __iced_k = __iced_k_noop;
      ___iced_passed_deferral = iced.findDeferral(arguments);
      this._last_count = null;
      _results = [];
      _while = (function(_this) {
        var count, delta, entropy, v, __iced_deferrals;
        return function(__iced_k) {
          var _break, _continue, _next;
          _break = function() {
            return __iced_k(_results);
          };
          _continue = function() {
            return iced.trampoline(function() {
              return _while(__iced_k);
            });
          };
          _next = function(__iced_next_arg) {
            _results.push(__iced_next_arg);
            return _continue();
          };
          if (!_this.running) {
            return _break();
          } else {
            if (_this.count_unused_bits() < _this.auto_stop_bits) {
              count = _this.millisecond_count();
              if ((_this._last_count != null) && (delta = count - _this._last_count)) {
                entropy = Math.floor(_this.log_2(Math.abs(delta)));
                entropy = Math.min(_this.max_bits_per_delta, entropy);
                v = [delta, entropy];
                _this.entropies.push(v);
              }
              _this._last_count = count;
            }
            (function(__iced_k) {
              __iced_deferrals = new iced.Deferrals(__iced_k, {
                parent: ___iced_passed_deferral,
                filename: "/Users/chris/git/more-entropy/src/generator.iced",
                funcname: "Generator.timer_race_loop"
              });
              _this.delay(__iced_deferrals.defer({
                lineno: 64
              }));
              __iced_deferrals._fulfill();
            })(_next);
          }
        };
      })(this);
      _while(__iced_k);
    };

    Generator.prototype.log_2 = function(x) {
      return Math.log(x) / Math.LN2;
    };

    Generator.prototype.millisecond_count = function() {
      var d, i, x;
      d = Date.now();
      i = x = 0;
      while (Date.now() < d + this.work_min + 1) {
        i++;
        x = Math.sin(Math.sqrt(Math.log(i + x)));
      }
      return i;
    };

    return Generator;

  })();

  if (typeof window !== "undefined" && window !== null) {
    window.Generator = Generator;
  }

  if (typeof exports !== "undefined" && exports !== null) {
    exports.Generator = Generator;
  }

}).call(this);
