// Generated by CoffeeScript 1.6.2
/* services.coffee
*/


(function() {
  var maBlur, maFocus, maLeadingSpacesCount, maMarkdown;

  angular.module('maComponents', []).directive("maBlur", maBlur = function() {
    return function(scope, elem, attrs) {
      return elem.bind("blur", function() {
        return scope.$apply(attrs.maBlur);
      });
    };
  }).directive("maFocus", maFocus = function($timeout) {
    return function(scope, elem, attrs) {
      return scope.$watch(attrs.maFocus, function(newVal) {
        if (newVal) {
          return $timeout((function() {
            return elem[0].focus();
          }), 0, false);
        }
      });
    };
  }).directive("maMarkdown", function() {
    return {
      restrict: 'E',
      link: function($scope, element, attrs) {
        var htmlText;

        htmlText = maMarkdown(element.text(), true, 'marked');
        return element.html(htmlText);
      }
    };
  }).directive("maGraph", function() {
    return {
      restrict: "E",
      replace: true,
      template: '<div class="maGraph"><div id="tip" ng-show="over"></div></div>',
      scope: {
        "jsondata": "=ngModel",
        "eventdata": "=maEvent",
        "height": "=height"
      },
      link: function($scope, element, attrs) {
        var animateOrigValue, attrWidth, glowstyle, height, mouseMove, mouseOut, mouseOver, over, paperClick, paperDraw, tipText;

        $(tip).hide();
        tipText = "";
        over = false;
        glowstyle = {
          width: 2,
          fill: false,
          opacity: 0.25,
          offsetx: 0,
          offsety: 0,
          color: "grey"
        };
        animateOrigValue = null;
        /*fade = (elem) ->
          ->
            elem.attr(
              fill: "#fff"
              r: 12
            ).animate(
              {
                fill: "#666"
                r: 8}
              , 500)
        */

        paperClick = function(elem, event) {
          var txt;

          txt = angular.toJson(elem.attrs);
          return $scope.eventdata = txt;
        };
        mouseOver = function(elem, event) {
          var i, pos, _i, _ref;

          tipText = elem.data("info");
          if (tipText) {
            if (elem.attrs.text) {
              if (animateOrigValue === null) {
                animateOrigValue = elem.attr("stroke");
                elem.animate({
                  "stroke": "grey",
                  "stroke-width": 0.5
                }, 200, "linear");
              }
            } else {
              elem.glw = elem.glow(glowstyle);
            }
            tipText = tipText.split("\n");
            for (i = _i = 0, _ref = tipText.length; _i < _ref; i = _i += 1) {
              if (tipText[i].length > 0) {
                pos = tipText[i].lastIndexOf(", ");
                if (pos > 0) {
                  tipText[i] = tipText[i].substring(0, pos + 2).italics() + tipText[i].substring(pos + 2).bold();
                } else if (tipText[i].charCodeAt(0) < "0".charCodeAt(0) || tipText[i].charCodeAt(0) > "9".charCodeAt(0)) {
                  tipText[i] = tipText[i].italics();
                }
              }
            }
            tipText = tipText.join("<br>");
            $(tip).stop(true, true).fadeIn();
            return over = true;
          }
        };
        mouseOut = function(elem, event) {
          $(tip).stop(true, true).fadeOut();
          over = false;
          if (elem.glw) {
            elem.glw.remove();
          }
          if (elem.attrs.text) {
            elem.animate({
              "stroke": animateOrigValue,
              "stroke-width": 0
            }, 200, "linear");
            return animateOrigValue = null;
          }
        };
        mouseMove = function(elem, event) {
          if (over) {
            $(tip).css("left", event.clientX + 5).css("top", event.clientY + 5 + angular.element(window).scrollTop());
            return $(tip).html(tipText);
          }
        };
        paperDraw = function() {
          var areaHeight, el, elarr, rec, recarr, txt, width, _i, _len, _ref;

          if (element.paper) {
            element.paper.remove();
          }
          width = element.paperWidth - 0;
          if (height) {
            areaHeight = height;
          } else {
            areaHeight = 1000;
          }
          element.paper = Raphael(attrs.id, width, areaHeight);
          if (attrs.stroke && (areaHeight != null)) {
            element.paper.rect(0, 0, width, areaHeight, 0).attr({
              stroke: attrs.stroke
            });
          }
          recarr = [];
          if ($scope.jsondata) {
            _ref = $scope.jsondata;
            for (_i = 0, _len = _ref.length; _i < _len; _i++) {
              rec = _ref[_i];
              recarr[0] = rec;
              elarr = element.paper.add(recarr);
              el = elarr[0];
              if (rec.data) {
                txt = rec.data;
                el.data("info", txt);
              }
              el.click(function(el) {
                return paperClick(this, el);
              });
              el.mouseover(function(el) {
                return mouseOver(this, el);
              });
              el.mouseout(function(el) {
                return mouseOut(this, el);
              });
              el.mousemove(function(el) {
                return mouseMove(this, el);
              });
            }
          }
        };
        if (attrs.height) {
          height = $scope.$eval(attrs.height);
        } else {
          height = element.height();
        }
        if (attrs.width) {
          attrWidth = $scope.$eval(attrs.width);
          element.paperWidth = element.width();
          if (attrWidth < element.paperWidth) {
            element.paperWidth = attrWidth;
          } else {
            if (element.paperWidth > element.width()) {
              element.paperWidth = element.width();
            }
            window.onresize = function() {
              element.paperWidth = window.innerWidth;
              if (element.paperWidth > element.width()) {
                element.paperWidth = element.width();
              }
              return paperDraw();
            };
          }
        } else {
          element.paperWidth = window.innerWidth;
          if (element.paperWidth > element.width()) {
            element.paperWidth = element.width();
          }
        }
        paperDraw();
        return $scope.$watch('jsondata', function(newValue) {
          return paperDraw();
        });
      }
    };
  }).directive("maGrid", function($parse) {
    return {
      restrict: "E",
      replace: true,
      template: '<div class="maGrid"></div>',
      scope: {
        "rowdata": "=ngModel"
      },
      link: function($scope, element, attrs, $rootScope) {
        var moveRowsPlugin, redraw, redrawRows;

        redrawRows = function(newScopeData) {
          element.dataView.beginUpdate();
          element.dataView.setItems(newScopeData.data);
          element.dataView.endUpdate();
          element.grid.updateRowCount();
          return element.grid.invalidate();
        };
        redraw = function(newScopeData) {
          element.dataView = new Slick.Data.DataView();
          element.grid = new Slick.Grid("#" + attrs.id, element.dataView, $scope.rowdata.columns, $scope.rowdata.options);
          element.grid.setSelectionModel(new Slick.RowSelectionModel());
          redrawRows(newScopeData);
          element.grid.onKeyDown.subscribe(function(e, args) {
            var activeCell, col, keyCode;

            keyCode = $.ui.keyCode;
            col = void 0;
            activeCell = this.getActiveCell();
            if (activeCell) {
              col = activeCell.cell;
              if (this.getColumns()[col].editor && !this.getCellEditor()) {
                if (jQuery.inArray(e.keyCode, [keyCode.LEFT, keyCode.RIGHT, keyCode.UP, keyCode.DOWN, keyCode.PAGE_UP, keyCode.PAGE_DOWN, keyCode.SHIFT, keyCode.CONTROL, keyCode.CAPS_LOCK, keyCode.HOME, keyCode.END, keyCode.INSERT, keyCode.TAB, keyCode.ENTER]) === -1) {
                  if (!(e.shiftKey || e.ctrlKey || e.altKey || e.ctrlKey || e.metaKey)) {
                    if (e.keyCode !== 20) {
                      return this.editActiveCell();
                    }
                  }
                }
              }
            }
          });
          element.grid.onCellChange.subscribe(function(e, args) {
            var column, fldName, rec, value;

            column = $scope.rowdata.columns[args.cell];
            fldName = column.field;
            value = args.item[fldName];
            if (column.type === "ar") {
              rec = $scope.rowdata.data[args.row];
              rec[fldName] = parseFloat(value);
            }
            return $scope.$apply(function() {
              return $scope.$emit("gridDataChanged", args.row, args.cell, fldName, value);
            });
          });
          element.grid.onSelectedRowsChanged.subscribe(function() {});
          element.dataView.onRowCountChanged.subscribe(function(e, args) {});
          element.dataView.onRowsChanged.subscribe(function(e, args) {
            element.grid.invalidateRows(args.rows);
            return element.grid.render();
          });
          /* When user clicks button, fetch data via Ajax, and bind it to the dataview.
          jQuery("#mybutton").click ->
            jQuery.getJSON my_url, (data) ->
              element.dataView.beginUpdate()
              element.dataView.setItems data
              element.dataView.endUpdate()
          */

          element.grid.onAddNewRow.subscribe(function(e, args) {
            var gridData, item;

            item = args.item;
            gridData = element.dataView.getItems();
            element.dataView.beginUpdate();
            gridData.push(item);
            return element.dataView.endUpdate();
          });
          return element.grid.onSort.subscribe(function(e, args) {
            var comparer, sortcol;

            comparer = function(a, b) {
              var x, y;

              x = a[sortcol];
              y = b[sortcol];
              if (x === y) {
                return 0;
              } else {
                if (x > y) {
                  return 1;
                } else {
                  return -1;
                }
              }
            };
            sortcol = args.sortCol.field;
            element.dataView.sort(comparer, args.sortAsc);
            return element.dataView.ref;
          });
          /*
          rows = element.dataView.getItems()
          rows.sort (a, b) ->
            result = (if a[field] > b[field] then 1 else (if a[field] < b[field] then -1 else 0))
            (if args.sortAsc then result else -result)
          element.grid.setData rows
          element.grid.updateRowCount()
          element.grid.render()
          */

        };
        $scope.$watch("rowdata", function(newValue) {
          if (newValue !== void 0) {
            return redraw(newValue);
          }
        });
        $scope.$on("refresh-ma-grid", function(event, modelToRedraw) {
          if (modelToRedraw === void 0) {
            return redraw($scope.rowdata);
          } else if (modelToRedraw === attrs.ngModel) {
            return redraw($scope.rowdata);
          } else if (modelToRedraw === "") {
            return redraw($scope.rowdata);
          }
        });
        if (!$scope.rowdata) {
          return;
        } else {
          redraw($scope.rowdata);
        }
        moveRowsPlugin = new Slick.RowMoveManager({
          cancelEditOnDrag: true
        });
        moveRowsPlugin.onBeforeMoveRows.subscribe(function(e, data) {
          var i;

          i = 0;
          while (i < data.rows.length) {
            if (data.rows[i] === data.insertBefore || data.rows[i] === data.insertBefore - 1) {
              e.stopPropagation();
              return false;
            }
            i++;
          }
          return true;
        });
        moveRowsPlugin.onMoveRows.subscribe(function(e, args) {
          var extractedRows, gridData, i, insertBefore, left, right, row, rows, selectedRows;

          extractedRows = [];
          left = void 0;
          right = void 0;
          rows = args.rows;
          insertBefore = args.insertBefore;
          gridData = element.dataView.getItems();
          left = gridData.slice(0, insertBefore);
          right = gridData.slice(insertBefore, gridData.length);
          rows.sort(function(a, b) {
            return a - b;
          });
          i = 0;
          while (i < rows.length) {
            extractedRows.push(gridData[rows[i]]);
            i++;
          }
          rows.reverse();
          i = 0;
          while (i < rows.length) {
            row = rows[i];
            if (row < insertBefore) {
              left.splice(row, 1);
            } else {
              right.splice(row - insertBefore, 1);
            }
            i++;
          }
          gridData = left.concat(extractedRows.concat(right));
          selectedRows = [];
          i = 0;
          while (i < rows.length) {
            selectedRows.push(left.length + i);
            i++;
          }
          element.grid.resetActiveCell();
          element.dataView.setData(gridData);
          element.grid.setSelectedRows(selectedRows);
          return element.grid.render();
        });
        element.grid.registerPlugin(moveRowsPlugin);
        element.grid.onDragInit.subscribe(function(e, dd) {
          return e.stopImmediatePropagation();
        });
        element.grid.onDragStart.subscribe(function(e, dd) {
          var cell, gridData, proxy, selectedRows;

          cell = element.grid.getCellFromEvent(e);
          if (!cell) {
            return;
          }
          dd.row = cell.row;
          gridData = element.dataView.getItems();
          if (!gridData[dd.row]) {
            return;
          }
          if (Slick.GlobalEditorLock.isActive()) {
            return;
          }
          e.stopImmediatePropagation();
          dd.mode = "recycle";
          selectedRows = element.grid.getSelectedRows();
          if (!selectedRows.length || jQuery.inArray(dd.row, selectedRows) === -1) {
            selectedRows = [dd.row];
            element.grid.setSelectedRows(selectedRows);
          }
          dd.rows = selectedRows;
          dd.count = selectedRows.length;
          proxy = jQuery("<span></span>").css({
            position: "absolute",
            display: "inline-block",
            padding: "4px 10px",
            background: "#e0e0e0",
            border: "1px solid gray",
            "z-index": 99999,
            "-moz-border-radius": "8px",
            "-moz-box-shadow": "2px 2px 6px silver"
          }).text("Drag to Recycle Bin to delete " + dd.count + " selected row(s)").appendTo("body");
          dd.helper = proxy;
          jQuery(dd.available).css("background", "pink");
          return proxy;
        });
        element.grid.onDrag.subscribe(function(e, dd) {
          if (dd.mode !== "recycle") {
            return;
          }
          e.stopImmediatePropagation();
          return dd.helper.css({
            top: e.pageY + 5,
            left: e.pageX + 5
          });
        });
        element.grid.onDragEnd.subscribe(function(e, dd) {
          if (dd.mode !== "recycle") {
            return;
          }
          e.stopImmediatePropagation();
          element.dataView.beginUpdate();
          dd.helper.remove();
          element.dataView.endUpdate();
          return jQuery(dd.available).css("background", "beige");
        });
        jQuery.drop({
          mode: "mouse"
        });
        return jQuery("#dropzone").bind("dropstart", function(e, dd) {
          if (dd.mode !== "recycle") {
            return;
          }
          return jQuery(this).css("background", "yellow");
        }).bind("dropend", function(e, dd) {
          if (dd.mode !== "recycle") {
            return;
          }
          return jQuery(dd.available).css("background", "pink");
        }).bind("drop", function(e, dd) {
          var gridData, i, rowsToDelete;

          if (dd.mode !== "recycle") {
            return;
          }
          rowsToDelete = dd.rows.sort().reverse();
          i = 0;
          gridData = element.dataView.getItems();
          while (i < rowsToDelete.length) {
            gridData.splice(rowsToDelete[i], 1);
            i++;
          }
          element.grid.invalidate();
          return element.grid.setSelectedRows([]);
        });
      }
    };
  });

  /*
  element.grid.onAddNewRow.subscribe (e, args) ->
    item =
      name: "New task"
      complete: false
    jQuery.extend item, args.item
    gridData = element.dataView.getItems()
    gridData.push item
    element.grid.invalidateRows [gridData.length - 1]
    element.grid.updateRowCount()
    element.grid.render()
  */


  /*
  
  # http://css.dzone.com/articles/websocket-webmotion-and
  # source copied from: http://svn.debux.org/webmotion-ext/dashboard/src/main/webapp/js/application.js
  
  
  # disable onclose handler first
  TaskCtrl = ($scope, TasksManager) ->
    $scope.addTask = ->
      TasksManager.addTask $scope.taskName
      $scope.taskName = ""
  
    $scope.updateTask = (element, status) ->
      id = element.attr("id")
      TasksManager.updateTask id, status
  
    $scope.delTask = (task) ->
      TasksManager.delTask task.id
  
    TasksManager.refresh = (tasks) ->
      $scope.tasks = tasks
      $scope.$digest()
  
    TasksManager.init()
  
  angular.module("components", []).directive("dragEvent", ["$parse", ($parse) ->
    ($scope, element, attrs) ->
      element.bind "dragstart", (evt) ->
        id = element.attr("id")
        evt.dataTransfer.setData "drag-id", id
        fn = $parse(attrs.dragEvent)
        fn $scope,
          $element: element
      element.attr "draggable", true
  
  ]).directive("dropEvent", ["$parse", ($parse) ->
    ($scope, element, attrs) ->
      element.bind "dragover dragenter", (evt) ->
        evt.stopPropagation()
        evt.preventDefault()
        false
  
      element.bind "drop", (evt) ->
        id = evt.dataTransfer.getData("drag-id")
        elementTransfer = angular.element(document.getElementById(id))
        element.append elementTransfer
        evt.stopPropagation()
        evt.preventDefault()
        fn = $parse(attrs.dropEvent)
        fn $scope,
          $element: elementTransfer
          $to: element
  
  
  ]).factory("WebSocket", ->
    connect: (url) ->
      self = this
      @connection = new WebSocket(url)
      @connection.onopen = ->
        self.onopen()  if @onopen
  
      @connection.onclose = ->
        self.onclose()  if @onclose
  
      @connection.onerror = (error) ->
        self.onerror error  if @onerror
  
      @connection.onmessage = (event) ->
        self.onmessage event  if @onmessage
  
    send: (message) ->
      @connection.send message
  
    close: ->
      @connection.onclose = ->
  
      @connection.close()
  ).factory "TasksManager", ->
    url = "ws://localhost:8080/dashboard/tasksManager"
    init: ->
      self = this
      @connection = new WebSocket(url)
      @connection.onopen = ->
        #log "connected"
        self.getTasks()
  
      @connection.onclose = ->
        #log "onclose"
  
      @connection.onerror = (error) ->
        #log error
  
      @connection.onmessage = (event) ->
        #log "refresh"
        data = angular.fromJson(event.data)
        self.refresh data.result
  
    getTasks: ->
      @sendMessage
        method: "getTasks"
        params: {}
  
  
    addTask: (name) ->
      @sendMessage
        method: "addTask"
        params:
          name: name
  
  
    updateTask: (id, status) ->
      @sendMessage
        method: "updateTask"
        params:
          id: id
          newStatus: status
  
  
    delTask: (id) ->
      @sendMessage
        method: "delTask"
        params:
          id: id
  
  
    sendMessage: (event) ->
      @connection.send JSON.stringify(event)
  
  angular.module "DashboardApp", ["components"]
  */


  /*
  TimerCtrl = ($scope, CurrentTime) ->
    $scope.CurrentTime = CurrentTime
    $scope.CurrentTime.setOnMessageCB (m) ->
      #log "message invoked in CurrentTimeCB: " + m
      #log m
      $scope.$apply ->
        $scope.currentTime = m.data
  
  
  TimerCtrl.$inject = ["$scope", "CurrentTime"]
  
  
  angular.module "TimerService", [], ($provide) ->
    $provide.factory "CurrentTime", ->
      onOpenCB = undefined
      onCloseCB = undefined
      onMessageCB = undefined
      location = "ws://localhost:3001/api/timer"
      ws = new WebSocket(location)
      ws.onopen = ->
        onOpenCB()  if onOpenCB isnt `undefined`
  
      ws.onclose = ->
        onCloseCB()  if onCloseCB isnt `undefined`
  
      ws.onmessage = (m) ->
        #log m
        onMessageCB m
  
      setOnOpenCB: (cb) ->
        onOpenCB = cb
  
      setOnCloseCB: (cb) ->
        onCloseCB = cb
  
      setOnMessageCB: (cb) ->
        onMessageCB = cb
  */


  maLeadingSpacesCount = function(str) {
    var i;

    i = 0;
    while (i < str.length) {
      if (str[i] !== " " && str[i] !== "\t" && str[i] !== "\n" && str[i] !== "\r") {
        return i;
      }
      i++;
    }
    return str.length;
  };

  maMarkdown = function(str, stripLeadingSpace, converter) {
    var htmlText, lineStart, options, pattern, spaceLen, tokens;

    if (stripLeadingSpace === true) {
      spaceLen = maLeadingSpacesCount(str);
      if (spaceLen > 0) {
        lineStart = str.substring(0, spaceLen);
        pattern = new RegExp(lineStart, 'g');
        str = str.replace(pattern, '\n');
      }
    }
    if (converter === 'showdown') {
      converter = new Showdown.converter();
      htmlText = converter.makeHtml(str);
    } else {
      /* https://github.com/chjj/marked
      marked has a few different switches which change behavior.
      
      pedantic: Conform to obscure parts of markdown.pl as much as possible. Don't fix any of the original markdown bugs or poor behavior.
      gfm: Enable github flavored markdown (enabled by default).
      sanitize: Sanitize the output. Ignore any HTML that has been input.
      highlight: A callback to highlight code blocks.
      tables: Enable GFM tables. This is enabled by default. (Requires the gfm option in order to be enabled).
      breaks: Enable GFM line breaks. Disabled by default.
      */

      options = {
        pedantic: false,
        gfm: true,
        sanitize: false,
        tables: true,
        breaks: false,
        highlight: null
      };
      /* highlight: (code, lang) ->
        if lang is "js"
          return highlighter.javascript(code)
        return code
      */

      tokens = marked.lexer(str, options);
      htmlText = marked.parser(tokens);
    }
    return htmlText;
  };

}).call(this);

/*
//@ sourceMappingURL=services.map
*/
