(function() {
  var $, $$, CompositeDisposable, DeprecationCopView, Disposable, Grim, ScrollView, fs, getSelectorDeprecations, marked, path, _, _ref, _ref1,
    __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

  _ref = require('atom'), Disposable = _ref.Disposable, CompositeDisposable = _ref.CompositeDisposable;

  _ref1 = require('atom-space-pen-views'), $ = _ref1.$, $$ = _ref1.$$, ScrollView = _ref1.ScrollView;

  path = require('path');

  _ = require('underscore-plus');

  fs = require('fs-plus');

  Grim = require('grim');

  marked = require('marked');

  getSelectorDeprecations = require('./helpers').getSelectorDeprecations;

  module.exports = DeprecationCopView = (function(_super) {
    __extends(DeprecationCopView, _super);

    function DeprecationCopView() {
      this.handleGrimUpdated = __bind(this.handleGrimUpdated, this);
      return DeprecationCopView.__super__.constructor.apply(this, arguments);
    }

    DeprecationCopView.content = function() {
      return this.div({
        "class": 'deprecation-cop pane-item native-key-bindings',
        tabindex: -1
      }, (function(_this) {
        return function() {
          return _this.div({
            "class": 'panel'
          }, function() {
            _this.div({
              "class": 'panel-heading'
            }, function() {
              _this.div({
                "class": 'btn-toolbar pull-right'
              }, function() {
                return _this.div({
                  "class": 'btn-group'
                }, function() {
                  return _this.button({
                    outlet: 'refreshCallsButton',
                    "class": 'btn refresh'
                  }, 'Refresh');
                });
              });
              return _this.span("Deprecated calls");
            });
            _this.ul({
              outlet: 'list',
              "class": 'list-tree has-collapsable-children'
            });
            _this.div({
              "class": 'panel-heading'
            }, function() {
              _this.div({
                "class": 'btn-toolbar pull-right'
              }, function() {
                return _this.div({
                  "class": 'btn-group'
                }, function() {
                  return _this.button({
                    outlet: 'refreshSelectorsButton',
                    "class": 'btn refresh-selectors'
                  }, 'Refresh');
                });
              });
              return _this.span("Deprecated selectors");
            });
            return _this.ul({
              outlet: 'selectorList',
              "class": 'selectors list-tree has-collapsable-children'
            });
          });
        };
      })(this));
    };

    DeprecationCopView.prototype.initialize = function(_arg) {
      this.uri = _arg.uri;
      this.subscriptions = new CompositeDisposable;
      this.subscriptions.add(Grim.on('updated', this.handleGrimUpdated));
      this.subscriptions.add(atom.packages.onDidActivateInitialPackages((function(_this) {
        return function() {
          return _this.refreshSelectorsButton.show();
        };
      })(this)));
      return this.subscriptions.add(atom.packages.onDidActivatePackage((function(_this) {
        return function(pack) {
          if (pack.isTheme()) {
            return _this.refreshSelectorsButton.show();
          }
        };
      })(this)));
    };

    DeprecationCopView.prototype.attached = function() {
      this.updateCalls();
      this.updateSelectors();
      return this.subscribeToEvents();
    };

    DeprecationCopView.prototype.subscribeToEvents = function() {
      if (this.subscribedToEvents) {
        return;
      }
      this.refreshCallsButton.on('click', (function(_this) {
        return function() {
          return _this.updateCalls();
        };
      })(this));
      this.refreshSelectorsButton.on('click', (function(_this) {
        return function() {
          return _this.updateSelectors();
        };
      })(this));
      this.on('click', '.deprecation-info', function() {
        return $(this).parent().toggleClass('collapsed');
      });
      this.on('click', '.stack-line-location, .source-url', function() {
        var pathToOpen;
        pathToOpen = this.href.replace('file://', '');
        if (process.platform === 'win32') {
          pathToOpen = pathToOpen.replace(/^\//, '');
        }
        return atom.open({
          pathsToOpen: [pathToOpen]
        });
      });
      this.on('click', '.issue-url', function() {
        var openExternally;
        if (process.platform !== 'win32') {
          return;
        }
        openExternally = (function(_this) {
          return function(urlToOpen) {
            if (urlToOpen == null) {
              urlToOpen = _this.href;
            }
            return require('shell').openExternal(urlToOpen);
          };
        })(this);
        $.ajax('http://git.io', {
          type: 'POST',
          data: {
            url: this.href
          },
          success: function(data, status, xhr) {
            return openExternally(xhr.getResponseHeader('Location'));
          },
          error: function() {
            return openExternally();
          }
        });
        return false;
      });
      return this.subscribedToEvents = true;
    };

    DeprecationCopView.prototype.destroy = function() {
      this.subscriptions.dispose();
      return this.detach();
    };

    DeprecationCopView.prototype.serialize = function() {
      return {
        deserializer: this.constructor.name,
        uri: this.getUri()
      };
    };

    DeprecationCopView.prototype.handleGrimUpdated = function() {
      return this.refreshCallsButton.show();
    };

    DeprecationCopView.prototype.getURI = function() {
      return this.uri;
    };

    DeprecationCopView.prototype.getTitle = function() {
      return 'Deprecation Cop';
    };

    DeprecationCopView.prototype.getIconName = function() {
      return 'alert';
    };

    DeprecationCopView.prototype.onDidChangeTitle = function() {
      return new Disposable;
    };

    DeprecationCopView.prototype.onDidChangeModified = function() {
      return new Disposable;
    };

    DeprecationCopView.prototype.getPackagePathsByPackageName = function() {
      var pack, _i, _len, _ref2;
      if (this.packagePathsByPackageName != null) {
        return this.packagePathsByPackageName;
      }
      this.packagePathsByPackageName = {};
      _ref2 = atom.packages.getLoadedPackages();
      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
        pack = _ref2[_i];
        this.packagePathsByPackageName[pack.name] = pack.path;
      }
      return this.packagePathsByPackageName;
    };

    DeprecationCopView.prototype.getPackageName = function(stack) {
      var fileName, functionName, i, location, packageName, packagePath, packagePaths, relativePath, resourcePath, _i, _ref2, _ref3;
      resourcePath = atom.getLoadSettings().resourcePath;
      packagePaths = this.getPackagePathsByPackageName();
      for (packageName in packagePaths) {
        packagePath = packagePaths[packageName];
        if (packagePath.indexOf('.atom/dev/packages') > -1 || packagePath.indexOf('.atom/packages') > -1) {
          packagePaths[packageName] = fs.absolute(packagePath);
        }
      }
      for (i = _i = 1, _ref2 = stack.length; 1 <= _ref2 ? _i < _ref2 : _i > _ref2; i = 1 <= _ref2 ? ++_i : --_i) {
        _ref3 = stack[i], functionName = _ref3.functionName, location = _ref3.location, fileName = _ref3.fileName;
        if (!fileName) {
          return;
        }
        for (packageName in packagePaths) {
          packagePath = packagePaths[packageName];
          relativePath = path.relative(packagePath, fileName);
          if (!/^\.\./.test(relativePath)) {
            return packageName;
          }
        }
      }
    };

    DeprecationCopView.prototype.createIssueUrl = function(packageName, deprecation, stack) {
      var body, repo, repoUrl, stacktrace, title, _ref2, _ref3, _ref4;
      if (!(repo = (_ref2 = atom.packages.getActivePackage(packageName)) != null ? (_ref3 = _ref2.metadata) != null ? _ref3.repository : void 0 : void 0)) {
        return;
      }
      repoUrl = (_ref4 = repo.url) != null ? _ref4 : repo;
      repoUrl = repoUrl.replace(/\.git$/, '');
      title = "" + (deprecation.getOriginName()) + " is deprecated.";
      stacktrace = stack.map(function(_arg) {
        var functionName, location;
        functionName = _arg.functionName, location = _arg.location;
        return "" + functionName + " (" + location + ")";
      }).join("\n");
      body = "" + (deprecation.getMessage()) + "\n```\n" + stacktrace + "\n```";
      return "" + repoUrl + "/issues/new?title=" + (encodeURI(title)) + "&body=" + (encodeURI(body));
    };

    DeprecationCopView.prototype.createSelectorIssueUrl = function(packageName, deprecation, sourcePath) {
      var body, repo, repoUrl, title, _ref2, _ref3, _ref4;
      if (!(repo = (_ref2 = atom.packages.getActivePackage(packageName)) != null ? (_ref3 = _ref2.metadata) != null ? _ref3.repository : void 0 : void 0)) {
        return;
      }
      repoUrl = (_ref4 = repo.url) != null ? _ref4 : repo;
      repoUrl = repoUrl.replace(/\.git$/, '');
      title = deprecation.message;
      body = "In " + sourcePath + ": " + deprecation.message;
      return "" + repoUrl + "/issues/new?title=" + (encodeURI(title)) + "&body=" + (encodeURI(body));
    };

    DeprecationCopView.prototype.updateCalls = function() {
      var deprecation, deprecations, packageDeprecations, packageName, packageNames, self, stack, stacks, _i, _j, _k, _len, _len1, _len2, _ref2, _ref3, _results;
      this.refreshCallsButton.hide();
      deprecations = Grim.getDeprecations();
      deprecations.sort(function(a, b) {
        return b.getCallCount() - a.getCallCount();
      });
      this.list.empty();
      packageDeprecations = {};
      for (_i = 0, _len = deprecations.length; _i < _len; _i++) {
        deprecation = deprecations[_i];
        stacks = deprecation.getStacks();
        stacks.sort(function(a, b) {
          return b.callCount - a.callCount;
        });
        for (_j = 0, _len1 = stacks.length; _j < _len1; _j++) {
          stack = stacks[_j];
          packageName = (_ref2 = (_ref3 = stack.metadata) != null ? _ref3.packageName : void 0) != null ? _ref2 : (this.getPackageName(stack) || '').toLowerCase();
          if (packageDeprecations[packageName] == null) {
            packageDeprecations[packageName] = [];
          }
          packageDeprecations[packageName].push({
            deprecation: deprecation,
            stack: stack
          });
        }
      }
      if (deprecations.length === 0) {
        return this.list.append($$(function() {
          return this.li({
            "class": 'list-item'
          }, "No deprecated calls");
        }));
      } else {
        self = this;
        packageNames = _.keys(packageDeprecations);
        packageNames.sort();
        _results = [];
        for (_k = 0, _len2 = packageNames.length; _k < _len2; _k++) {
          packageName = packageNames[_k];
          _results.push(this.list.append($$(function() {
            return this.li({
              "class": 'deprecation list-nested-item collapsed'
            }, (function(_this) {
              return function() {
                _this.div({
                  "class": 'deprecation-info list-item'
                }, function() {
                  _this.span({
                    "class": 'text-highlight'
                  }, packageName || 'atom core');
                  return _this.span(" (" + (_.pluralize(packageDeprecations[packageName].length, 'deprecation')) + ")");
                });
                return _this.ul({
                  "class": 'list'
                }, function() {
                  var _l, _len3, _ref4, _ref5, _results1;
                  _ref4 = packageDeprecations[packageName];
                  _results1 = [];
                  for (_l = 0, _len3 = _ref4.length; _l < _len3; _l++) {
                    _ref5 = _ref4[_l], deprecation = _ref5.deprecation, stack = _ref5.stack;
                    _results1.push(_this.li({
                      "class": 'list-item deprecation-detail'
                    }, function() {
                      _this.span({
                        "class": 'text-warning icon icon-alert'
                      });
                      _this.div({
                        "class": 'list-item deprecation-message'
                      }, function() {
                        return _this.raw(marked(deprecation.getMessage()));
                      });
                      _this.div({
                        "class": 'btn-toolbar'
                      }, function() {
                        var url;
                        _this.span("Called " + (_.pluralize(stack.callCount, 'time')));
                        if (packageName && (url = self.createIssueUrl(packageName, deprecation, stack))) {
                          return _this.a({
                            "class": 'issue-url',
                            href: url
                          }, "Create Issue on " + packageName + " repo");
                        }
                      });
                      return _this.div({
                        "class": 'stack-trace'
                      }, function() {
                        var fileName, functionName, location, _len4, _m, _ref6, _results2;
                        _results2 = [];
                        for (_m = 0, _len4 = stack.length; _m < _len4; _m++) {
                          _ref6 = stack[_m], functionName = _ref6.functionName, location = _ref6.location, fileName = _ref6.fileName;
                          _results2.push(_this.div({
                            "class": 'stack-line'
                          }, function() {
                            _this.span(functionName);
                            _this.span(" - ");
                            return _this.a({
                              "class": 'stack-line-location',
                              href: location
                            }, location);
                          }));
                        }
                        return _results2;
                      });
                    }));
                  }
                  return _results1;
                });
              };
            })(this));
          })));
        }
        return _results;
      }
    };

    DeprecationCopView.prototype.updateSelectors = function() {
      var deprecationsByFile, packageName, self, _ref2, _results;
      this.refreshSelectorsButton.hide();
      this.selectorList.empty();
      self = this;
      _ref2 = getSelectorDeprecations();
      _results = [];
      for (packageName in _ref2) {
        deprecationsByFile = _ref2[packageName];
        _results.push(this.selectorList.append($$(function() {
          return this.li({
            "class": 'deprecation list-nested-item collapsed'
          }, (function(_this) {
            return function() {
              _this.div({
                "class": 'deprecation-info list-item'
              }, function() {
                return _this.span({
                  "class": 'text-highlight'
                }, packageName);
              });
              return _this.ul({
                "class": 'list'
              }, function() {
                var deprecations, sourcePath, _results1;
                _results1 = [];
                for (sourcePath in deprecationsByFile) {
                  deprecations = deprecationsByFile[sourcePath];
                  _results1.push(_this.li({
                    "class": 'list-item source-file'
                  }, function() {
                    _this.a({
                      "class": 'source-url',
                      href: path.join(deprecations[0].packagePath, sourcePath)
                    }, sourcePath);
                    return _this.ul({
                      "class": 'list'
                    }, function() {
                      var deprecation, _i, _len, _results2;
                      _results2 = [];
                      for (_i = 0, _len = deprecations.length; _i < _len; _i++) {
                        deprecation = deprecations[_i];
                        _results2.push(_this.li({
                          "class": 'list-item'
                        }, function() {
                          _this.span({
                            "class": 'text-warning icon icon-alert'
                          });
                          _this.span({
                            "class": 'list-item deprecation-message'
                          }, deprecation.message);
                          return _this.div({
                            "class": 'btn-toolbar'
                          }, function() {
                            var url;
                            if (url = self.createSelectorIssueUrl(packageName, deprecation, sourcePath)) {
                              return _this.a({
                                "class": 'issue-url',
                                href: url
                              }, "Create Issue on " + packageName + " repo");
                            }
                          });
                        }));
                      }
                      return _results2;
                    });
                  }));
                }
                return _results1;
              });
            };
          })(this));
        })));
      }
      return _results;
    };

    return DeprecationCopView;

  })(ScrollView);

}).call(this);
