(function() {
  var GitHubFile, Range, Shell, parseUrl;

  Shell = require('shell');

  Range = require('atom').Range;

  parseUrl = require('url').parse;

  module.exports = GitHubFile = (function() {
    GitHubFile.fromPath = function(filePath) {
      return new GitHubFile(filePath);
    };

    function GitHubFile(filePath) {
      var rootDir, rootDirIndex;
      this.filePath = filePath;
      rootDir = atom.project.relativizePath(filePath)[0];
      if (rootDir != null) {
        rootDirIndex = atom.project.getPaths().indexOf(rootDir);
        this.repo = atom.project.getRepositories()[rootDirIndex];
      }
    }

    GitHubFile.prototype.open = function(lineRange) {
      if (this.isOpenable()) {
        return this.openUrlInBrowser(this.blobUrl() + this.getLineRangeSuffix(lineRange));
      } else {
        return this.reportValidationErrors();
      }
    };

    GitHubFile.prototype.blame = function(lineRange) {
      if (this.isOpenable()) {
        return this.openUrlInBrowser(this.blameUrl() + this.getLineRangeSuffix(lineRange));
      } else {
        return this.reportValidationErrors();
      }
    };

    GitHubFile.prototype.history = function() {
      if (this.isOpenable()) {
        return this.openUrlInBrowser(this.historyUrl());
      } else {
        return this.reportValidationErrors();
      }
    };

    GitHubFile.prototype.copyUrl = function(lineRange) {
      if (this.isOpenable()) {
        return atom.clipboard.write(this.blobUrl() + this.getLineRangeSuffix(lineRange));
      } else {
        return this.reportValidationErrors();
      }
    };

    GitHubFile.prototype.openBranchCompare = function() {
      if (this.isOpenable()) {
        return this.openUrlInBrowser(this.branchCompareUrl());
      } else {
        return this.reportValidationErrors();
      }
    };

    GitHubFile.prototype.openRepository = function() {
      if (this.isOpenable()) {
        return this.openUrlInBrowser(this.githubRepoUrl());
      } else {
        return this.reportValidationErrors();
      }
    };

    GitHubFile.prototype.getLineRangeSuffix = function(lineRange) {
      var endRow, startRow;
      if (lineRange && atom.config.get('open-on-github.includeLineNumbersInUrls')) {
        lineRange = Range.fromObject(lineRange);
        startRow = lineRange.start.row + 1;
        endRow = lineRange.end.row + 1;
        if (startRow === endRow) {
          return "#L" + startRow;
        } else {
          return "#L" + startRow + "-L" + endRow;
        }
      } else {
        return '';
      }
    };

    GitHubFile.prototype.isOpenable = function() {
      return this.validationErrors().length === 0;
    };

    GitHubFile.prototype.validationErrors = function() {
      if (!this.repo) {
        return ["No repository found for path: " + this.filePath + "."];
      }
      if (!this.gitUrl()) {
        return ["No URL defined for remote: " + (this.remoteName())];
      }
      if (!this.githubRepoUrl()) {
        return ["Remote URL is not hosted on GitHub: " + (this.gitUrl())];
      }
      return [];
    };

    GitHubFile.prototype.reportValidationErrors = function() {
      var message;
      message = this.validationErrors().join('\n');
      return atom.notifications.addWarning(message);
    };

    GitHubFile.prototype.openUrlInBrowser = function(url) {
      return Shell.openExternal(url);
    };

    GitHubFile.prototype.blobUrl = function() {
      return "" + (this.githubRepoUrl()) + "/blob/" + (this.encodeSegments(this.branchName())) + "/" + (this.encodeSegments(this.repoRelativePath()));
    };

    GitHubFile.prototype.blameUrl = function() {
      return "" + (this.githubRepoUrl()) + "/blame/" + (this.encodeSegments(this.branchName())) + "/" + (this.encodeSegments(this.repoRelativePath()));
    };

    GitHubFile.prototype.historyUrl = function() {
      return "" + (this.githubRepoUrl()) + "/commits/" + (this.encodeSegments(this.branchName())) + "/" + (this.encodeSegments(this.repoRelativePath()));
    };

    GitHubFile.prototype.branchCompareUrl = function() {
      return "" + (this.githubRepoUrl()) + "/compare/" + (this.encodeSegments(this.branchName()));
    };

    GitHubFile.prototype.encodeSegments = function(segments) {
      if (segments == null) {
        segments = '';
      }
      segments = segments.split('/');
      segments = segments.map(function(segment) {
        return encodeURIComponent(segment);
      });
      return segments.join('/');
    };

    GitHubFile.prototype.gitUrl = function() {
      var remoteOrBestGuess, _ref;
      remoteOrBestGuess = (_ref = this.remoteName()) != null ? _ref : 'origin';
      return this.repo.getConfigValue("remote." + remoteOrBestGuess + ".url", this.filePath);
    };

    GitHubFile.prototype.githubRepoUrl = function() {
      var url;
      url = this.gitUrl();
      if (url.match(/https:\/\/[^\/]+\//)) {
        url = url.replace(/\.git$/, '');
      } else if (url.match(/git@[^:]+:/)) {
        url = url.replace(/^git@([^:]+):(.+)$/, function(match, host, repoPath) {
          repoPath = repoPath.replace(/^\/+/, '');
          return ("http://" + host + "/" + repoPath).replace(/\.git$/, '');
        });
      } else if (url.match(/ssh:\/\/git@([^\/]+)\//)) {
        url = "http://" + (url.substring(10).replace(/\.git$/, ''));
      } else if (url.match(/^git:\/\/[^\/]+\//)) {
        url = "http" + (url.substring(3).replace(/\.git$/, ''));
      }
      url = url.replace(/\/+$/, '');
      if (!this.isBitbucketUrl(url)) {
        return url;
      }
    };

    GitHubFile.prototype.isBitbucketUrl = function(url) {
      var host;
      if (url.indexOf('git@bitbucket.org') === 0) {
        return true;
      }
      try {
        host = parseUrl(url).host;
        return host === 'bitbucket.org';
      } catch (_error) {}
    };

    GitHubFile.prototype.repoRelativePath = function() {
      return this.repo.getRepo(this.filePath).relativize(this.filePath);
    };

    GitHubFile.prototype.remoteName = function() {
      var branchRemote, shortBranch;
      shortBranch = this.repo.getShortHead(this.filePath);
      if (!shortBranch) {
        return null;
      }
      branchRemote = this.repo.getConfigValue("branch." + shortBranch + ".remote", this.filePath);
      if (!((branchRemote != null ? branchRemote.length : void 0) > 0)) {
        return null;
      }
      return branchRemote;
    };

    GitHubFile.prototype.branchName = function() {
      var branchMerge, shortBranch;
      shortBranch = this.repo.getShortHead(this.filePath);
      if (!shortBranch) {
        return null;
      }
      branchMerge = this.repo.getConfigValue("branch." + shortBranch + ".merge", this.filePath);
      if (!((branchMerge != null ? branchMerge.length : void 0) > 11)) {
        return shortBranch;
      }
      if (branchMerge.indexOf('refs/heads/') !== 0) {
        return shortBranch;
      }
      return branchMerge.substring(11);
    };

    return GitHubFile;

  })();

}).call(this);
