// Generated by CoffeeScript 1.7.1
(function() {
  var TabManager, method, methods, noop, _escape, _i, _len;

  window.WEB_SOCKET_SWF_LOCATION = '/static/main/WebSocketMain.swf';

  window.Stream = (function() {
    function Stream() {
      $('#connection-error').hide();
    }

    Stream.prototype.start = function() {
      this.socket = ajentiConnectSocket('/stream');
      this.socket.on('connect', function() {
        return $('#connection-error').hide();
      });
      this.socket.on('auth-error', function() {
        console.log('Authentication lost!');
        return location.reload();
      });
      this.socket.on('reconnect_failed', function() {
        return this.start();
      });
      this.socket.on('error', function(err) {
        return console.error('Socket error:', err);
      });
      this.socket.on('disconnect', function() {
        return $('#connection-error').show();
      });
      this.socket.on('init', function(data) {
        data = JSON.parse(data);
        this.serverInfo = data;
        console.group('Welcome to Ajenti');
        console.log('version', data.version);
        console.log('running on', data.platform);
        console.log('your session:', data.session);
        $('title').text(data.hostname);
        console.groupEnd();
        Feedback.configure(data.feedback, data.platform, data.version, data.edition);
        Feedback.emit('Login');
        return ajentiCrashResume();
      });
      this.socket.on('ui', function(ui) {
        console.group('Received update');
        console.log('Transfer size', ui.length);
        if (this.serverInfo.compression) {
          profiler.start('Decompressing');
          if (this.serverInfo.compression === 'zlib') {
            ui = RawDeflate.inflate(RawDeflate.Base64.decode(ui));
          }
          if (this.serverInfo.compression === 'lzw') {
            ui = lzw_decode(RawDeflate.Base64.decode(ui));
          }
          profiler.stop();
          console.log('Payload size', ui.length);
        }
        ui = JSON.parse(ui);
        console.log('JSON data:', ui);
        UI.clear();
        profiler.start('Cumulative UI inflating');
        ui = UI.inflate(ui);
        profiler.stop();
        profiler.start('Cumulative UI update');
        UI.replace(ui);
        profiler.stop();
        $('#version-number').text("v" + this.serverInfo.version);
        console.log('Total elements:', UI._total_elements);
        console.groupEnd();
        return Loading.hide();
      });
      this.socket.on('ack', function() {
        return Loading.hide();
      });
      this.socket.on('update-request', function() {
        UI.checkForUpdates();
        UI.sendUpdates(true);
        return Loading.show();
      });
      this.socket.on('progress-message', function(m) {
        console.log('Server progress update:', m);
        Loading.setMessage(m);
        if (m) {
          return Loading.show();
        } else {
          return Loading.hide();
        }
      });
      this.socket.on('crash', function(data) {
        data = JSON.parse(data);
        console.log('CRASH:', data);
        ajentiCrash(data);
        return Loading.hide();
      });
      this.socket.on('security-error', function() {
        console.log('SECURITY ERROR');
        ajentiSecurityError();
        return Loading.hide();
      });
      this.socket.on('notify', function(data) {
        data = JSON.parse(data);
        return Notificator.notify(data.type, data.text);
      });
      this.socket.on('openTab', function(data) {
        data = JSON.parse(data);
        return Tabs.addTab(data.url, data.title);
      });
      this.socket.on('closeTab', function(data) {
        data = JSON.parse(data);
        return Tabs.closeTab(data.url);
      });
      return this.socket.on('debug', function(data) {
        var d;
        data = JSON.parse(data);
        console.group('Server-side profiling');
        for (d in data.profiles) {
          console.log(d, data.profiles[d].toFixed(3), 's');
        }
        return console.groupEnd();
      });
    };

    Stream.prototype.send = function(message) {
      console.log('Sending updates', message);
      this.socket.send(JSON.stringify(message));
      return Loading.show();
    };

    Stream.prototype.emit_ui_update = function(updates) {
      return this.send({
        type: 'ui_update',
        content: updates
      });
    };

    return Stream;

  })();

  window.UIManager = (function() {
    function UIManager(stream) {
      this.stream = stream;
      this.ui = null;
      this.pendingUpdates = [];
      this.updaterTimeout = null;
    }

    UIManager.prototype.inflate = function(json) {
      var attr_defaults, attr_map, child, children, cls, k, properties, typeid, v, _fn, _i, _len, _ref, _ref1;
      properties = {};
      attr_defaults = {
        visible: true,
        client: false
      };
      attr_map = {
        _c: 'children',
        _t: 'typeid',
        _s: 'style'
      };
      for (k in json) {
        v = json[k];
        properties[(_ref = attr_map[k]) != null ? _ref : k] = v;
      }
      for (k in attr_defaults) {
        v = attr_defaults[k];
        if (properties[k] === void 0) {
          properties[k] = v;
        }
      }
      children = [];
      this._total_elements += 1;
      if (properties.visible === true) {
        _ref1 = properties.children;
        _fn = (function(_this) {
          return function(child) {
            return children.push(_this.inflate(child));
          };
        })(this);
        for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
          child = _ref1[_i];
          _fn(child);
        }
      }
      typeid = properties.typeid.replace(':', '__');
      cls = Controls[typeid];
      if (!cls) {
        cls = Controls["default"];
      }
      return new cls(this, properties, children);
    };

    UIManager.prototype.clear = function() {
      this._total_elements = 0;
      if (this.ui) {
        this.ui.broadcast('destruct');
      }
      $('.root *').unbind();
      $('.root')[0].innerHTML = '';
      return delete this.ui;
    };

    UIManager.prototype.replace = function(ui) {
      var dom;
      $('.ui-tooltip').remove();
      this.ui = ui;
      dom = $$(ui.html);
      $('.root').append(dom);
      profiler.start('DOM setup');
      profiler.setupDomStats = {};
      ui.setupDom(dom);
      console.log(profiler.setupDomStats);
      return profiler.stop();
    };

    UIManager.prototype.extractUpdates = function(control, target) {
      var child, updates, _fn, _i, _len, _ref;
      _ref = control.children;
      _fn = (function(_this) {
        return function(child) {
          return _this.extractUpdates(child, target);
        };
      })(this);
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        child = _ref[_i];
        _fn(child);
      }
      updates = control.extractUpdates();
      if (updates) {
        return target.push(updates);
      }
    };

    UIManager.prototype.checkForUpdates = function() {
      var update, updates, _i, _len, _results;
      updates = [];
      this.extractUpdates(this.ui, updates);
      _results = [];
      for (_i = 0, _len = updates.length; _i < _len; _i++) {
        update = updates[_i];
        _results.push((function(_this) {
          return function(update) {
            return _this.queueUpdate(update);
          };
        })(this)(update));
      }
      return _results;
    };

    UIManager.prototype.queueUpdate = function(update) {
      return this.pendingUpdates.push(update);
    };

    UIManager.prototype.sendUpdates = function(force) {
      if (force == null) {
        force = false;
      }
      if (this.updaterTimeout) {
        clearTimeout(this.updaterTimeout);
      }
      return this.updaterTimeout = setTimeout((function(_this) {
        return function() {
          if (force || _this.pendingUpdates.length > 0) {
            _this.stream.emit_ui_update(_this.pendingUpdates);
          }
          _this.pendingUpdates = [];
          return _this.updaterTimeout = null;
        };
      })(this), 50);
    };

    UIManager.prototype.event = function(control, event, params) {
      var update;
      this.checkForUpdates();
      update = {
        type: 'event',
        uid: control.uid,
        event: event,
        params: params != null ? params : null
      };
      this.queueUpdate(update);
      return this.sendUpdates();
    };

    UIManager.prototype.restoreTheme = function() {
      if (getCookie('ajenti-theme') === 'dark') {
        return this.toggleTheme();
      }
    };

    UIManager.prototype.toggleTheme = function() {
      $('html').toggleClass('ui-dark');
      $('html').toggleClass('ui-light');
      if ($('html').hasClass('ui-dark')) {
        return setCookie('ajenti-theme', 'dark');
      } else {
        return setCookie('ajenti-theme', 'light');
      }
    };

    return UIManager;

  })();

  window.LoadingDim = (function() {
    function LoadingDim(dom) {
      this.dom = dom;
      this.visible = true;
      this.dom.show();
      this.follow = this.dom.find('.wrapper');
      this.dom.mousemove((function(_this) {
        return function(e) {
          if (_this.visible) {
            _this.follow.show();
            return _this.follow.css({
              left: (e.clientX + 20) + 'px',
              top: (e.clientY + 20) + 'px'
            });
          }
        };
      })(this));
    }

    LoadingDim.prototype.hide = function() {
      this.visible = false;
      this.setMessage('');
      $('.hide-when-loaded').hide();
      $('body').removeClass('loading');
      this.dom.hide();
      return this.follow.hide();
    };

    LoadingDim.prototype.show = function() {
      this.visible = true;
      $('body').addClass('loading');
      return this.dom.show();
    };

    LoadingDim.prototype.setMessage = function(m) {
      return this.dom.find('.message').text(m);
    };

    return LoadingDim;

  })();

  TabManager = (function() {
    function TabManager() {
      this.mainTab = $('#tab-ajenti');
      this.tabHeadersDom = $('#tab-headers');
      this.tabsDom = $('#tabs');
      this.tabHeadersDom.find('a').click((function(_this) {
        return function() {
          return _this.goHome();
        };
      })(this));
      this.goHome();
      this.openTabs = {};
    }

    TabManager.prototype.goHome = function() {
      this.tabsDom.children().hide();
      this.mainTab.show();
      this.tabHeadersDom.find('a').removeClass('active');
      return $(this.tabHeadersDom.find('a')[0]).addClass('active');
    };

    TabManager.prototype.addTab = function(url, title) {
      var dom, headerDom;
      if (this.openTabs[url]) {
        this.openTabs[url].click();
        return;
      }
      dom = $("<div class=\"tab\"><iframe src=\"" + url + "\" /></div>");
      this.tabsDom.append(dom);
      headerDom = $("<a href=\"#\">" + title + "<span class=\"close\"><i class=\"icon-remove\"></span></a></a>");
      this.tabHeadersDom.append(headerDom);
      this.openTabs[url] = headerDom;
      this.openTabs[url].dom = dom;
      headerDom.click((function(_this) {
        return function() {
          _this.tabsDom.children().hide();
          dom.show();
          setTimeout(function() {
            var cw, iframe;
            iframe = dom.find('iframe')[0];
            cw = iframe.contentWindow;
            if (cw) {
              return cw.focus();
            }
          }, 100);
          _this.tabHeadersDom.find('a').removeClass('active');
          return headerDom.addClass('active');
        };
      })(this));
      headerDom.find('.close').click((function(_this) {
        return function(e) {
          _this.closeTab(url);
          e.stopPropagation();
          return e.preventDefault();
        };
      })(this));
      return headerDom.click();
    };

    TabManager.prototype.closeTab = function(url) {
      this.openTabs[url].dom[0].innerHTML = '';
      this.openTabs[url].dom.remove();
      this.openTabs[url].remove();
      delete this.openTabs[url];
      return this.goHome();
    };

    return TabManager;

  })();

  $(function() {
    window.Loading = new LoadingDim($('#loading'));
    window.Tabs = new TabManager();
    if (window.UI) {
      UI.restoreTheme();
      return $('#ui-theme-toggle').click(function() {
        return UI.toggleTheme();
      });
    }
  });

  window.Controls = {};

  window.Control = (function() {
    function Control(ui, properties, children) {
      var child, children_html, _base, _base1, _i, _len;
      this.ui = ui;
      this.properties = properties;
      if ((_base = window.Control).lastUID == null) {
        _base.lastUID = -1;
      }
      if (this.properties == null) {
        this.properties = {};
      }
      if ((_base1 = this.properties).visible == null) {
        _base1.visible = true;
      }
      if (this.properties.uid) {
        this.uid = this.properties.uid;
      } else {
        this.uid = window.Control.lastUID--;
      }
      this.dom = null;
      this.children = [];
      this.childCount = children ? children.length : 0;
      this.changed = false;
      profiler.start('Generating DOM');
      this.html = this.createDom();
      this.html = this.html.trim();
      if (!this.noUID) {
        this.html = this.html.insert(this.html.indexOf('>'), " id=\"uid-" + this.uid + "\"");
      }
      profiler.stop();
      children_html = '';
      if (children) {
        for (_i = 0, _len = children.length; _i < _len; _i++) {
          child = children[_i];
          if (child.properties.visible || this.requiresAllChildren) {
            this.children.push(child);
            children_html += this.wrapChild(child);
          }
        }
      }
      this.html = this.html.replace('<children>', children_html);
    }

    Control.prototype.s = function(value) {
      return ('' + value).replace(/&/g, '&amp;').replace(/'/g, '&apos;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    };

    Control.prototype.createDom = function() {
      return "";
    };

    Control.prototype.setupDom = function(dom) {
      var child, childDom, key, _base, _i, _len, _ref;
      if (this.dom) {
        return;
      }
      if (!dom && !this.noUID) {
        dom = $$(this.html);
      }
      this.dom = dom;
      if (this.properties.visible !== true && this.dom && this.dom.style) {
        this.dom.style.display = 'none';
        return this;
      }
      _ref = this.children;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        child = _ref[_i];
        if (child.properties.visible || this.requiresAllChildren) {
          if (child.dom) {
            this.append(child);
          } else {
            if (Control.prototype.setupDom !== child.constructor.prototype.setupDom) {
              key = child.constructor.name;
              if ((_base = profiler.setupDomStats)[key] == null) {
                _base[key] = 0;
              }
              profiler.setupDomStats[key] += 1;
            }
            childDom = document.getElementById('uid-' + child.properties.uid);
            if (!childDom && !child.noUID) {
              console.error('Pre-generated DOM not found for', child);
            }
            child.setupDom(childDom);
          }
        }
      }
      return this;
    };

    Control.prototype.destruct = function() {};

    Control.prototype.detectUpdates = function() {
      return {};
    };

    Control.prototype.markChanged = function() {
      if (!this.changed) {
        $(this.dom).before("<div class=\"changed-badge\">\n    <span title=\"Not saved yet\">*</span>\n</div>");
      }
      this.changed = true;
      return $(this.dom).addClass('changed');
    };

    Control.prototype.wrapChild = function(child) {
      return child.html;
    };

    Control.prototype.wrapChildLive = function(child) {
      return child.dom;
    };

    Control.prototype.onBroadcast = function(msg) {};

    Control.prototype.broadcast = function(msg) {
      var c, _i, _len, _ref, _results;
      this.onBroadcast(msg);
      _ref = this.children;
      _results = [];
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        c = _ref[_i];
        _results.push((function(_this) {
          return function(c) {
            return c.broadcast(msg);
          };
        })(this)(c));
      }
      return _results;
    };

    Control.prototype.extractUpdates = function() {
      var k, updates, _fn;
      updates = this.detectUpdates();
      if (!this.uid || $.isEmptyObject(updates)) {
        return null;
      }
      _fn = (function(_this) {
        return function(k) {
          return _this.properties[k] = updates[k];
        };
      })(this);
      for (k in updates) {
        _fn(k);
      }
      return {
        type: 'update',
        uid: this.uid,
        properties: updates
      };
    };

    Control.prototype.append = function(child) {
      var wrapper;
      if (!this.childContainer) {
        this.childContainer = $(this.dom).find2('.__child-container').first();
      }
      wrapper = this.wrapChildLive(child);
      if (wrapper instanceof jQuery) {
        wrapper = wrapper[0];
      }
      if (wrapper) {
        return this.childContainer.append(wrapper);
      }
    };

    Control.prototype.publish = function() {
      this.ui.checkForUpdates();
      return this.ui.sendUpdates();
    };

    Control.prototype.event = function(event, params) {
      var localHandler;
      this.ui.checkForUpdates();
      localHandler = this['on_' + event];
      if (localHandler) {
        if (!localHandler(params)) {
          return false;
        }
      }
      if (!this.uid || this.properties.client) {
        return false;
      }
      this.ui.event(this, event, params);
      return true;
    };

    Control.prototype._int_to_px = function(i) {
      if (/^[0-9]+$/.test(i)) {
        return i + 'px';
      }
      if (!i || i === 'auto') {
        return 'auto';
      }
      return i + '';
    };

    Control.prototype.cancel = function(event) {
      event.preventDefault();
      return event.stopPropagation();
    };

    return Control;

  })();

  _escape = function(s) {
    return s.replace(/</g, '&lt;');
  };

  window.ajentiConnectSocket = function(uri) {
    var cfg;
    cfg = {
      resource: 'ajenti:socket',
      'reconnection limit': 1,
      'max reconnection attempts': 999999
    };
    if (/Apple Computer/.test(navigator.vendor) && location.protocol === 'https:') {
      cfg.transports = ['xhr-polling', 'jsonp-polling'];
    }
    return io.connect(uri, cfg);
  };

  window.ajentiCrash = function(info) {
    $('#crash').show();
    $('#crash-traceback').html(_escape(info.message + "\n" + info.traceback));
    return $('#crash-report textarea').val(info.report);
  };

  window.ajentiCrashResume = function() {
    return $('#crash').hide();
  };

  window.ajentiCrashShowReport = function() {
    $('#crash-traceback').toggle('blind');
    $('#crash-report').toggle('blind');
    return setTimeout((function(_this) {
      return function() {
        return $('#crash-report textarea').focus()[0].select();
      };
    })(this), 1000);
  };

  window.ajentiSecurityError = function() {
    return $('#security-error').show();
  };

  window.ajentiSecurityResume = function(info) {
    return $('#security-error').hide();
  };

  $.fn.safeRemove = function() {
    return this.each(function(i, e) {
      if (e.parentNode) {
        return e.parentNode.removeChild(e);
      }
    });
  };

  $.fn.find2 = function(selector) {
    return this.find(selector).add(this.filter(selector));
  };

  String.prototype.trim = function() {
    return String(this).replace(/^\s+|\s+$/g, '');
  };

  String.prototype.insert = function(index, string) {
    if (index > 0) {
      return this.substring(0, index) + string + this.substring(index, this.length);
    } else {
      return string + this;
    }
  };

  $(function() {
    if (location.protocol === 'http:' && location.hostname !== 'localhost') {
      return $('#ssl-alert').show();
    }
  });

  if (/Android|webOS|iPad|IEMobile/i.test(navigator.userAgent)) {
    $(function() {
      $('html').addClass('mode-tablet');
      return FastClick.attach(document.body);
    });
  }

  window.$$ = function(html, container) {
    var div;
    if (container == null) {
      container = 'div';
    }
    div = document.createElement(container);
    div.innerHTML = html;
    return div.childNodes[0];
  };

  noop = function() {
    return null;
  };

  methods = ['assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error', 'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log', 'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd', 'timeStamp', 'trace', 'warn'];

  window.console = window.console || {};

  for (_i = 0, _len = methods.length; _i < _len; _i++) {
    method = methods[_i];
    if (!console[method]) {
      console[method] = noop;
    }
  }

}).call(this);
