(function() {

  this.def_tag('PANEL_TAG',"NODE_TAG",function(__scope,__class){

    if(!this.__ctor__){this.__ctor__= function PANEL_TAG(){__class.__super__.__ctor__.apply(this, arguments)}; this.__ctor__.prototype = this.prototype; }

    this.prototype.translate = function(x, y, z) {
      return this["@node"].style.webkitTransform = "translate3d(" + x + "px," + y + "px," + (z || 0) + ")";
    }; __method_added(this,"translate");

    this.prototype.ontouchstart = function(touch) {
      return true;
    }; __method_added(this,"ontouchstart");

    this.prototype.ontouchmove = function(touch) {
      var box, x, y;
      box = touch["@target_bbox"];
      x = box.left + touch["@movedX"];
      y = box.top + touch["@movedY"];
      return this.translate(x, y);
    }; __method_added(this,"ontouchmove");

    this.prototype.ontap = function() {
      return true;
    }; __method_added(this,"ontap");

  });

  this.def_tag('TOOLS_TAG_ID',"NODE_TAG",function(__scope,__class){

    if(!this.__ctor__){this.__ctor__= function TOOLS_TAG_ID(){__class.__super__.__ctor__.apply(this, arguments)}; this.__ctor__.prototype = this.prototype; }

    this.prototype["selected="] = function(tool) {
      if (this["@selected"] !== tool) {
        if (this["@selected"]) this["@selected"]["disable!"]();
        this["@selected"] = tool;
        if (tool) this["@selected"]["enable!"]();
        this.parent()["tool="](tool);
      }
      return tool;
    }; __method_added(this,"selected=");

    this.prototype.selected = function() {
      return this["@selected"];
    }; __method_added(this,"selected");

  });

  this.def_tag('TOOL_TAG',"NODE_TAG",function(__scope,__class){

    if(!this.__ctor__){this.__ctor__= function TOOL_TAG(){__class.__super__.__ctor__.apply(this, arguments)}; this.__ctor__.prototype = this.prototype; }

    this.prototype["shortcut="] = function(shortcut) {
      var el;
      this['[]=']('shortcut',shortcut);
      if (!(el = __sel([['.shortcut']], this))) {
        el = __tag('div',null,[ "shortcut"],{});
        this.append(el);
      }
      return el["text="](shortcut);
    }; __method_added(this,"shortcut=");

    this.prototype.ontap = function() {
      this.parent()["selected="](this);
      return true;
    }; __method_added(this,"ontap");

    this.prototype.ontouchstart = function(touch, editor) {
      var c, c2, cinc, cx, cx2, i, i2, lvl, r, r2, rci, rinc;
      if (!editor) return true;
      this["@active"] = true;
      this["@meta"] = touch["meta?"]();
      this["@shift"] = touch["shift?"]();
      this["@alt"] = touch["alt?"]();
      this["@force"] = true;
      this["@rci"] || (this["@rci"] = [0, 0, 0]);
      rci = this.rci_for_touch(touch);
      if (touch["shift?"]()) {
        r = this["@rci"][0];
        c = this["@rci"][1];
        cx = c * 2 + r % 2;
        i = this["@rci"][2];
        r2 = rci[0];
        c2 = rci[1];
        cx2 = c2 * 2 + r2 % 2;
        i2 = rci[2];
        this.p(cx2 - cx, r2 - r);
        lvl = __tagid('app').level();
        if (r === r2 && i !== i2) {
          cinc = c > c2 && -1 || 1;
          while (c !== c2) {
            c += cinc;
            i = lvl.rc_to_i(r, c);
            this["rci="]([r, c, i]);
          }
        } else if (r % 2 === r2 % 2 && c === c2) {
          while (i !== i2) {
            r += r2 > r ? 2 : -2;
            i = lvl.rc_to_i(r, c);
            this["rci="]([r, c, i]);
          }
        } else if ($abs(cx2 - cx) === $abs(r2 - r)) {
          cinc = cx2 > cx && 1 || -1;
          rinc = r2 > r && 1 || -1;
          while (i !== i2) {
            if (r % 2 && cinc > 0) c++;
            if (r % 2 === 0 && cinc < 0) c--;
            r += rinc;
            i = lvl.rc_to_i(r, c);
            this["rci="]([r, c, i]);
          }
        } else {
          this["rci="](rci);
        }
      } else {
        this["rci="](rci);
      }
      this["@force"] = false;
      return true;
    }; __method_added(this,"ontouchstart");

    this.prototype.ontouchmove = function(touch, editor) {
      if (!editor) return;
      this["@meta"] = touch["meta?"]();
      this["@shift"] = touch["shift?"]();
      return this["rci="](this.rci_for_touch(touch));
    }; __method_added(this,"ontouchmove");

    this.prototype.onmousemove = function() {
      return true;
    }; __method_added(this,"onmousemove");

    this.prototype.ontouchend = function(touch) {
      this["@active"] = false;
      this["@touch"] = null;
      this["@meta"] = null;
      this["@alt"] = null;
      return this["@shift"] = null;
    }; __method_added(this,"ontouchend");

    this.prototype["enable!"] = function() {
      this.flag('selected');
      return __tagid('app')['[]=']('tool',this.class()["@type"]);
    }; __method_added(this,"enable!");

    this.prototype["disable!"] = function() {
      return this.unflag('selected');
    }; __method_added(this,"disable!");

    this.prototype.rci_for_touch = function(touch) {
      var i, rc;
      rc = $tosrp(touch["@x"], touch["@y"]);
      i = __tagid('app').level().rc_to_i(rc.r, rc.c);
      return [rc.r, rc.c, i];
    }; __method_added(this,"rci_for_touch");

    this.prototype["rci="] = function(rci) {
      if (!this["@rci"] || rci[2] !== this["@rci"][2] || this["@force"]) {
        this["@rci"] = rci;
        if (this["@active"]) this["use!"]();
      }
      return rci;
    }; __method_added(this,"rci=");

    this.prototype["use!"] = function() {
      return true;
    }; __method_added(this,"use!");

  });

  this.def_tag('BRUSHTOOL_TAG',"TOOL_TAG",function(__scope,__class){

    if(!this.__ctor__){this.__ctor__= function BRUSHTOOL_TAG(){__class.__super__.__ctor__.apply(this, arguments)}; this.__ctor__.prototype = this.prototype; }

    this.prototype.block = function() {
      if (this["@meta"]) {
        return __scope.Block.empty;
      } else {
        return this["@block"];
      }
    }; __method_added(this,"block");

    this.prototype.ontouchend = function(touch) {
      __class.__super__.prototype.ontouchend.apply(this, arguments);
      return __tagid('app').level().save();
    }; __method_added(this,"ontouchend");

    this.prototype["use!"] = function() {
      return __tagid('app')["@level"].grid()['[]='](this["@rci"][2],this.block()["@char"]);
    }; __method_added(this,"use!");

  });

  this.def_tag('BLOCKTOOL_TAG',"BRUSHTOOL_TAG",function(__scope,__class){

    this.__ctor__ = function BLOCKTOOL_TAG(node, options) {
      __class.__super__.__ctor__.apply(this, arguments);
      this["@block"] = options.block;
      this.flag(this["@block"]["@name"]);
      return this;
    }; this.__ctor__.prototype = this.prototype;;

  });

  this.def_tag('CUSTOMBRUSHTOOL_TAG',"BRUSHTOOL_TAG",function(__scope,__class){

    if(!this.__ctor__){this.__ctor__= function CUSTOMBRUSHTOOL_TAG(){__class.__super__.__ctor__.apply(this, arguments)}; this.__ctor__.prototype = this.prototype; }

    this.prototype["enable!"] = function() {
      this["@enabled"] = true;
      this["@pattern"] = __tagid('brushcanvas');
      __tagid('foreground').append(this["@pattern"]);
      this["@pattern"].translate(-200, 0);
      __tagid('brushpanel').hide();
      return __class.__super__.prototype['enable!'].apply(this, arguments);
    }; __method_added(this,"enable!");

    this.prototype["disable!"] = function() {
      __class.__super__.prototype['disable!'].apply(this, arguments);
      this["@enabled"] = false;
      this["@pattern"].translate(0, 0);
      __tagid('brushpanel').append(__tagid('brushcanvas'));
      return __tagid('brushpanel').show();
    }; __method_added(this,"disable!");

    this.prototype.onmousemove = function(event) {
      var rc, x, y;
      if (!this["@enabled"]) return;
      rc = $tosrp(event.clientX, event.clientY);
      if (rc.r !== this["@r"] || rc.c !== this["@c"]) {
        this["@r"] = rc.r;
        this["@c"] = rc.c;
        x = this["@c"] * $block_size + (this["@r"] % 2) * ($block_size / 2) - 80;
        y = this["@r"] * ($block_size / 2) - 80;
        this["@pattern"].translate(x, -y);
      }
      return true;
    }; __method_added(this,"onmousemove");

    this.prototype.block = function() {
      return nil;
    }; __method_added(this,"block");

    this.prototype["use!"] = function() {
      var app, c, idx, r, rci, rcp, _i, _len, _primitive, _ref;
      app = __tagid('app');
      rci = this["@rci"];
      _ref = __tagid('brushpanel').pattern();
      for (_i = 0, _len = (_ref.len ? _ref.len() : _ref.length),_primitive = (_ref instanceof Array || !_ref.at); _i < _len; _i++) {
        rcp = _primitive ? _ref[_i] : _ref.at(_i);
        r = rci[0] + rcp[0] - 5;
        c = rci[1] + rcp[1] - 2;
        if ((rcp[0] % 2) === 0 && (rci[0] % 2) === 0) c--;
        idx = app.level().rc_to_i(r, c);
        app["@level"].grid()['[]='](idx,this["@meta"] ? __scope.Block.empty["@char"] : rcp[2]);
      }
      return this;
    }; __method_added(this,"use!");

  });

  this.def_tag('TIMERTOOL_TAG',"TOOL_TAG",function(__scope,__class){

    if(!this.__ctor__){this.__ctor__= function TIMERTOOL_TAG(){__class.__super__.__ctor__.apply(this, arguments)}; this.__ctor__.prototype = this.prototype; }

    this.prototype.ontouchend = function(touch) {
      __class.__super__.prototype.ontouchend.apply(this, arguments);
      this["@selecting"] = false;
      return __tagid('app').level().save();
    }; __method_added(this,"ontouchend");

    this.prototype["use!"] = function() {
      var config, timer;
      var _this = this;
      if (timer = __tagid('editor')["@timers"]['[]'](this["@rci"][2])) {
        if (!this["@selecting"] && !this["@shift"] && !this["@meta"]) {
          __msel([['timerblock','.selected']])["deselect!"]();
        }
        if (!__msel([['timerblock','.selected']]).count()) {
          __tagid('timerpanel')["config="](timer.config());
        }
        timer["select!"]();
        if (this["@alt"]) {
          config = __scope.JSON.stringify(timer.config());
          __tagid('app').level().timers().each_pair(function(k, v) {
            var t;
            if (v === config && (t = __tagid('editor')["@timers"]['[]'](k))) {
              return t["select!"]();
            }
          });
        }
        return this["@selecting"] = true;
      } else if (!this["@selecting"]) {
        config = __tagid('timerpanel').config();
        if (!this["@shift"] && !this["@meta"]) {
          __msel([['timerblock','.selected']])["deselect!"]();
        }
        return __tagid('app').level().timers()['[]='](this["@rci"][2],__scope.JSON.stringify(config));
      }
    }; __method_added(this,"use!");

  });

  this.def_tag('TIMERBLOCK_TAG',"NODE_TAG",function(__scope,__class){

    this.prototype.translate = function(x, y, z) {
      return this["@node"].style.webkitTransform = "translate3d(" + x + "px," + y + "px," + (z || 0) + ")";
    }; __method_added(this,"translate");

    this.__ctor__ = function TIMERBLOCK_TAG(node, options) {
      var cols, reps;
      var _this = this;
      __class.__super__.__ctor__.apply(this, arguments);
      reps = __tagid('editor')["@repeats"];
      cols = __tagid('app').level().width();
      (0).upto(reps, function(i) {
        var el;
        el = __tag('div',null,[ "timeblock"],{});
        el.css('left', i * cols * $block_size);
        return _this.append(el);
      });
      this["@scheduled"] = false;
      this["@distance"] = 0;
      this["@block_state"] = false;
      return this;
    }; this.__ctor__.prototype = this.prototype;;

    this.prototype.tick = function(frames) {
      if (!this["@scheduled"]) return;
      return this["frame="](frames);
    }; __method_added(this,"tick");

    this.prototype.freeze = function(distance) {
      return this["frame="](8 * (this["@r"] + distance));
    }; __method_added(this,"freeze");

    this.prototype["schedule!"] = function() {
      return this["@scheduled"] = true;
    }; __method_added(this,"schedule!");

    this.prototype["unschedule!"] = function() {
      if (!this["@scheduled"]) return;
      return this["@scheduled"] = false;
    }; __method_added(this,"unschedule!");

    this.prototype["activate!"] = function() {
      this.unflag('inactive');
      return this["@block_state"] = true;
    }; __method_added(this,"activate!");

    this.prototype["deactivate!"] = function() {
      this.flag('inactive');
      return this["@block_state"] = false;
    }; __method_added(this,"deactivate!");

    this.prototype["frame="] = function(frame) {
      var delay, period, period_time, state, tick;
      period_time = this["@on_period"] + this["@off_period"];
      delay = this["@r"] * this["@row_delay"] + (this["@c"] * 2 + this["@r"] % 2) * this["@col_delay"];
      while (delay > this["@r"] * 8) {
        delay -= period_time;
      }
      tick = frame - this["@own_delay"] - delay;
      if (tick >= 0 && this["@on_period"] > 0) {
        period = __scope.Math.floor(tick / (this["@on_period"] + this["@off_period"]));
        tick -= period * (this["@on_period"] + this["@off_period"]);
        state = !!(tick >= this["@on_period"]);
        if (this["@start_state"]) state = !state;
      } else {
        state = !!this["@start_state"];
      }
      if (state !== this["@block_state"]) {
        if (state) {
          this["activate!"]();
        } else {
          this["deactivate!"]();
        }
      }
    }; __method_added(this,"frame=");

    this.prototype["index="] = function(idx) {
      var rc, x, y;
      this["@index"] = idx;
      rc = __tagid('app').level().i_to_rc(idx);
      this["@r"] = rc['[]'](0);
      this["@c"] = rc['[]'](1);
      x = this["@c"] * $block_size + (this["@r"] % 2) * ($block_size / 2);
      y = this["@r"] * ($block_size / 2);
      return this.translate(x, -y);
    }; __method_added(this,"index=");

    this.prototype["config="] = function(config) {
      this["@start_state"] = !!config['[]'](0);
      this["@on_period"] = config['[]'](1);
      this["@off_period"] = config['[]'](2);
      this["@row_delay"] = config['[]'](3);
      this["@col_delay"] = config['[]'](4);
      this["@own_delay"] = config['[]'](5);
      this["schedule!"]();
      __tagid('app').level().timers()['[]='](this["@index"],__scope.JSON.stringify(config));
      return this;
    }; __method_added(this,"config=");

    this.prototype.config = function() {
      return [this["@start_state"] && 1 || 0, this["@on_period"], this["@off_period"], this["@row_delay"], this["@col_delay"], this["@own_delay"]];
    }; __method_added(this,"config");

    this.prototype.ontouchstart = function() {
      return true;
    }; __method_added(this,"ontouchstart");

    this.prototype["deselect!"] = function() {
      return this.unflag('selected');
    }; __method_added(this,"deselect!");

    this.prototype["select!"] = function() {
      return this.flag('selected');
    }; __method_added(this,"select!");

    this.prototype["selected?"] = function() {
      return this["flagged?"]('selected');
    }; __method_added(this,"selected?");

    this.prototype["destroy!"] = function() {
      __tagid('app').level().timers()['[]='](this["@index"],nil);
      this["deactivate!"]();
      return this.hide();
    }; __method_added(this,"destroy!");

    this.prototype.ontap = function(touch) {
      if (touch["shift?"]()) {
        if (this["selected?"]()) {
          this["deselect!"]();
        } else {
          this["select!"]();
        }
      } else {
        __msel([['timerblock','.selected']])["deselect!"]();
        this["select!"]();
        __tagid('timerpanel')["config="](this.config());
      }
      return true;
    }; __method_added(this,"ontap");

  });

  this.def_tag('TIMERPANEL_TAG_ID',"PANEL_TAG",function(__scope,__class){

    if(!this.__ctor__){this.__ctor__= function TIMERPANEL_TAG_ID(){__class.__super__.__ctor__.apply(this, arguments)}; this.__ctor__.prototype = this.prototype; }

    this.prototype["config="] = function(values) {
      this["@silent"] = true;
      __sel([['.start_state']], this)["value="](values['[]'](0) && 1 || 0);
      __sel([['.on']], this)["value="](values['[]'](1));
      __sel([['.off']], this)["value="](values['[]'](2));
      __sel([['.row_delay']], this)["value="](values['[]'](3));
      __sel([['.col_delay']], this)["value="](values['[]'](4));
      __sel([['.own_delay']], this)["value="](values['[]'](5));
      return this["@silent"] = false;
    }; __method_added(this,"config=");

    this.prototype.config = function() {
      return [__sel([['.start_state']], this).value() && 1 || 0, __sel([['.on']], this).value(), __sel([['.off']], this).value(), __sel([['.row_delay']], this).value(), __sel([['.col_delay']], this).value(), __sel([['.own_delay']], this).value()];
    }; __method_added(this,"config");

    this.prototype.onformchange = function(event) {
      var block, i, _len, _primitive, _ref;
      if (this["@silent"]) return true;
      __msel([['timerblock','.selected']])["config="](this.config());
      __tagid('app').level().save();
      _ref = __msel([['timerblock','.selected']]);
      for (i = 0, _len = (_ref.len ? _ref.len() : _ref.length),_primitive = (_ref instanceof Array || !_ref.at); i < _len; i++) {
        block = _primitive ? _ref[i] : _ref.at(i);
        this.p('iterating selected nodes', i, block);
      }
      return true;
    }; __method_added(this,"onformchange");

    this.prototype.remove_selected = function() {
      __msel([['timerblock','.selected']])["destroy!"]();
      __tagid('app').level().save();
      return true;
    }; __method_added(this,"remove_selected");

    this.prototype.apply = function() {
      __msel([['timerblock','.selected']])["config="](this.config());
      __tagid('app').level().save();
      return true;
    }; __method_added(this,"apply");

  });

  this.def_tag('BRUSHCANVAS_TAG_ID',"CANVAS_TAG",function(__scope,__class){

    if(!this.__ctor__){this.__ctor__= function BRUSHCANVAS_TAG_ID(){__class.__super__.__ctor__.apply(this, arguments)}; this.__ctor__.prototype = this.prototype; }

    this.prototype.translate = function(x, y, z) {
      return this["@node"].style.webkitTransform = "translate3d(" + x + "px," + y + "px," + (z || 0) + ")";
    }; __method_added(this,"translate");

    this.prototype.awaken = function() {
      var _this = this;
      this["@size"] = 6;
      this["height="](this["@height"] = this["@size"] * 32);
      this["width="](this["@width"] = this["@size"] * 32);
      this["@brush"] = new (__ctor(__scope.Brush))({
        width: this["@size"]
      });
      this["@brush"].grid().on('change', function(idx, char) {
        return _this.draw_block(_this["@brush"].i_to_rc(idx), char);
      });
      this.draw_image("/blocks/empty-brush.png", 0, 0, $block_size, $block_size);
      return this;
    }; __method_added(this,"awaken");

    this.prototype.idx_for_touch = function(touch) {
      var c, r, srp;
      srp = $tosrp(touch["@event"].offsetX, touch["@event"].offsetY, this["@height"], 0);
      r = srp.r;
      c = srp.c;
      if (r < 1 || r >= this["@size"] * 2 || (r % 2 === 0 && (c < 1 || c > (this["@size"] - 1)))) {
        return nil;
      }
      return this["@brush"].rc_to_i(r, c);
    }; __method_added(this,"idx_for_touch");

    this.prototype.ontouchstart = function(touch) {
      var idx;
      if (!__tagid('tools').selected()) return;
      if (!__tagid('tools').selected()["@block"]) return;
      this["@paint"] = true;
      this["@erase"] = touch["meta?"]();
      if (idx = this.idx_for_touch(touch)) this["idx="](idx);
      return true;
    }; __method_added(this,"ontouchstart");

    this.prototype.ontouchmove = function(touch) {
      var idx;
      this["@erase"] = touch["meta?"]();
      if (idx = this.idx_for_touch(touch)) return this["idx="](idx);
    }; __method_added(this,"ontouchmove");

    this.prototype.ontouchend = function(touch) {
      this["@paint"] = false;
      return this["@idx"] = null;
    }; __method_added(this,"ontouchend");

    this.prototype["idx="] = function(idx) {
      if (this["@idx"] !== idx) {
        this["@idx"] = idx;
        if (this["@paint"]) this["paint!"]();
      }
      return idx;
    }; __method_added(this,"idx=");

    this.prototype["paint!"] = function() {
      var brush;
      if (brush = __tagid('tools').selected()["@block"]) {
        return this["@brush"].grid()['[]='](this["@idx"],this["@erase"] ? __scope.Block.empty["@char"] : brush["@char"]);
      }
    }; __method_added(this,"paint!");

    this.prototype["rotate!"] = function() {
      var rotated;
      var _this = this;
      rotated = [];
      this.pattern().each(function(rc) {
        var c, r;
        r = rc['[]'](0);
        c = rc['[]'](1) * 2 + r % 2;
        rotated.push([c - _this["@size"], -r + _this["@size"], rc['[]'](2)]);
        return _this["@brush"].grid()['[]='](rc['[]'](3),__scope.Block.empty["@char"]);
      });
      rotated.each(function(rc) {
        var c, i, r;
        r = rc['[]'](0) + _this["@size"];
        c = rc['[]'](1) + _this["@size"];
        c = (c - r % 2) / 2;
        i = _this["@brush"].rc_to_i(r, c);
        return _this["@brush"].grid()['[]='](i,rc['[]'](2));
      });
      return this;
    }; __method_added(this,"rotate!");

    this.prototype.pattern = function() {
      var points;
      var _this = this;
      points = [];
      this["@brush"].grid().each(function(block, i) {
        var rc;
        rc = _this["@brush"].i_to_rc(i);
        rc['[]='](2,block);
        rc['[]='](3,i);
        if (block && block !== __scope.Block.empty["@char"]) {
          return points.push(rc);
        }
      });
      return points;
    }; __method_added(this,"pattern");

    this.prototype.draw_block = function(rc, char) {
      var type, x, y;
      type = __scope.Block[char];
      x = rc['[]'](1) * $block_size + (rc['[]'](0) % 2) * ($block_size / 2) - ($block_size / 2);
      y = this["@height"] - rc['[]'](0) * ($block_size / 2) - ($block_size / 2);
      this.draw_image("/blocks/empty-brush.png", x, y, $block_size, $block_size);
      if (type && type !== __scope.Block.empty) {
        this.draw_image("/blocks/" + type["@name"] + ".png", x, y, $block_size, $block_size);
      }
    }; __method_added(this,"draw_block");

  });

  this.def_tag('BRUSHPANEL_TAG_ID',"PANEL_TAG",function(__scope,__class){

    if(!this.__ctor__){this.__ctor__= function BRUSHPANEL_TAG_ID(){__class.__super__.__ctor__.apply(this, arguments)}; this.__ctor__.prototype = this.prototype; }

    this.prototype.pattern = function() {
      return __tagid('brushcanvas').pattern();
    }; __method_added(this,"pattern");

  });

  this.def_tag('TIMINGS_TAG_ID',"PANEL_TAG",function(__scope,__class){

    if(!this.__ctor__){this.__ctor__= function TIMINGS_TAG_ID(){__class.__super__.__ctor__.apply(this, arguments)}; this.__ctor__.prototype = this.prototype; }



  });

}).call($$base);

