(function() {
  var $, SymbolsView, TagGenerator, fs, path, temp;

  path = require('path');

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

  fs = require('fs-plus');

  temp = require('temp');

  SymbolsView = require('../lib/symbols-view');

  TagGenerator = require('../lib/tag-generator');

  describe("SymbolsView", function() {
    var activationPromise, directory, editor, getEditorView, getWorkspaceView, symbolsView, _ref;
    _ref = [], symbolsView = _ref[0], activationPromise = _ref[1], editor = _ref[2], directory = _ref[3];
    getWorkspaceView = function() {
      return atom.views.getView(atom.workspace);
    };
    getEditorView = function() {
      return atom.views.getView(atom.workspace.getActiveTextEditor());
    };
    beforeEach(function() {
      atom.project.setPaths([temp.mkdirSync("other-dir-"), temp.mkdirSync('atom-symbols-view-')]);
      directory = atom.project.getDirectories()[1];
      fs.copySync(path.join(__dirname, 'fixtures', 'js'), atom.project.getPaths()[1]);
      activationPromise = atom.packages.activatePackage("symbols-view");
      return jasmine.attachToDOM(getWorkspaceView());
    });
    describe("when tags can be generated for a file", function() {
      beforeEach(function() {
        return waitsForPromise(function() {
          return atom.workspace.open(directory.resolve('sample.js'));
        });
      });
      it("initially displays all JavaScript functions with line numbers", function() {
        runs(function() {
          return atom.commands.dispatch(getEditorView(), "symbols-view:toggle-file-symbols");
        });
        waitsForPromise(function() {
          return activationPromise;
        });
        runs(function() {
          symbolsView = $(getWorkspaceView()).find('.symbols-view').view();
          return expect(symbolsView.loading).toBeVisible();
        });
        waitsFor(function() {
          return symbolsView.list.children('li').length > 0;
        });
        return runs(function() {
          expect(symbolsView.loading).toBeEmpty();
          expect($(getWorkspaceView()).find('.symbols-view')).toExist();
          expect(symbolsView.list.children('li').length).toBe(2);
          expect(symbolsView.list.children('li:first').find('.primary-line')).toHaveText('quicksort');
          expect(symbolsView.list.children('li:first').find('.secondary-line')).toHaveText('Line 1');
          expect(symbolsView.list.children('li:last').find('.primary-line')).toHaveText('quicksort.sort');
          expect(symbolsView.list.children('li:last').find('.secondary-line')).toHaveText('Line 2');
          return expect(symbolsView.error).not.toBeVisible();
        });
      });
      it("caches tags until the editor changes", function() {
        runs(function() {
          editor = atom.workspace.getActiveTextEditor();
          return atom.commands.dispatch(getEditorView(), "symbols-view:toggle-file-symbols");
        });
        waitsForPromise(function() {
          return activationPromise;
        });
        runs(function() {
          return symbolsView = $(getWorkspaceView()).find('.symbols-view').view();
        });
        waitsFor(function() {
          return symbolsView.list.children('li').length > 0;
        });
        runs(function() {
          symbolsView.cancel();
          spyOn(symbolsView, 'generateTags').andCallThrough();
          return atom.commands.dispatch(getEditorView(), "symbols-view:toggle-file-symbols");
        });
        waitsFor(function() {
          return symbolsView.list.children('li').length > 0;
        });
        runs(function() {
          expect(symbolsView.loading).toBeEmpty();
          expect(symbolsView.list.children('li').length).toBe(2);
          expect(symbolsView.generateTags).not.toHaveBeenCalled();
          editor.save();
          symbolsView.cancel();
          return atom.commands.dispatch(getEditorView(), "symbols-view:toggle-file-symbols");
        });
        waitsFor(function() {
          return symbolsView.list.children('li').length > 0;
        });
        return runs(function() {
          expect(symbolsView.loading).toBeEmpty();
          expect(symbolsView.list.children('li').length).toBe(2);
          expect(symbolsView.generateTags).toHaveBeenCalled();
          editor.destroy();
          return expect(symbolsView.cachedTags).toEqual({});
        });
      });
      it("displays an error when no tags match text in mini-editor", function() {
        runs(function() {
          return atom.commands.dispatch(getEditorView(), "symbols-view:toggle-file-symbols");
        });
        waitsForPromise(function() {
          return activationPromise;
        });
        runs(function() {
          return symbolsView = $(getWorkspaceView()).find('.symbols-view').view();
        });
        waitsFor(function() {
          return symbolsView.list.children('li').length > 0;
        });
        return runs(function() {
          symbolsView.filterEditorView.setText("nothing will match this");
          window.advanceClock(symbolsView.inputThrottle);
          expect($(getWorkspaceView()).find('.symbols-view')).toExist();
          expect(symbolsView.list.children('li').length).toBe(0);
          expect(symbolsView.error).toBeVisible();
          expect(symbolsView.error.text().length).toBeGreaterThan(0);
          symbolsView.filterEditorView.setText("");
          window.advanceClock(symbolsView.inputThrottle);
          expect(symbolsView.list.children('li').length).toBe(2);
          return expect(symbolsView.error).not.toBeVisible();
        });
      });
      return it("moves the cursor to the selected function", function() {
        runs(function() {
          expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([0, 0]);
          expect($(getWorkspaceView()).find('.symbols-view')).not.toExist();
          return atom.commands.dispatch(getEditorView(), "symbols-view:toggle-file-symbols");
        });
        waitsFor(function() {
          return $(getWorkspaceView()).find('.symbols-view').find('li').length;
        });
        return runs(function() {
          $(getWorkspaceView()).find('.symbols-view').find('li:eq(1)').mousedown().mouseup();
          return expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([1, 2]);
        });
      });
    });
    describe("when tags can't be generated for a file", function() {
      beforeEach(function() {
        return waitsForPromise(function() {
          return atom.workspace.open('sample.txt');
        });
      });
      return it("shows an error message when no matching tags are found", function() {
        runs(function() {
          return atom.commands.dispatch(getEditorView(), "symbols-view:toggle-file-symbols");
        });
        waitsForPromise(function() {
          return activationPromise;
        });
        runs(function() {
          return symbolsView = $(getWorkspaceView()).find('.symbols-view').view();
        });
        waitsFor(function() {
          return symbolsView.error.isVisible();
        });
        return runs(function() {
          expect(symbolsView).toExist();
          expect(symbolsView.list.children('li').length).toBe(0);
          expect(symbolsView.error).toBeVisible();
          expect(symbolsView.error.text().length).toBeGreaterThan(0);
          return expect(symbolsView.loadingArea).not.toBeVisible();
        });
      });
    });
    describe("TagGenerator", function() {
      it("generates tags for all JavaScript functions", function() {
        var tags;
        tags = [];
        waitsForPromise(function() {
          var sampleJsPath;
          sampleJsPath = directory.resolve('sample.js');
          return new TagGenerator(sampleJsPath).generate().then(function(o) {
            return tags = o;
          });
        });
        return runs(function() {
          expect(tags.length).toBe(2);
          expect(tags[0].name).toBe("quicksort");
          expect(tags[0].position.row).toBe(0);
          expect(tags[1].name).toBe("quicksort.sort");
          return expect(tags[1].position.row).toBe(1);
        });
      });
      return it("generates no tags for text file", function() {
        var tags;
        tags = [];
        waitsForPromise(function() {
          var sampleJsPath;
          sampleJsPath = directory.resolve('sample.txt');
          return new TagGenerator(sampleJsPath).generate().then(function(o) {
            return tags = o;
          });
        });
        return runs(function() {
          return expect(tags.length).toBe(0);
        });
      });
    });
    describe("go to declaration", function() {
      it("doesn't move the cursor when no declaration is found", function() {
        waitsForPromise(function() {
          return atom.workspace.open(directory.resolve("tagged.js"));
        });
        runs(function() {
          editor = atom.workspace.getActiveTextEditor();
          editor.setCursorBufferPosition([0, 2]);
          return atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
        });
        waitsForPromise(function() {
          return activationPromise;
        });
        return runs(function() {
          return expect(editor.getCursorBufferPosition()).toEqual([0, 2]);
        });
      });
      it("moves the cursor to the declaration when there is a single matching declaration", function() {
        waitsForPromise(function() {
          return atom.workspace.open(directory.resolve("tagged.js"));
        });
        runs(function() {
          editor = atom.workspace.getActiveTextEditor();
          editor.setCursorBufferPosition([6, 24]);
          spyOn(SymbolsView.prototype, "moveToPosition").andCallThrough();
          return atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
        });
        waitsFor(function() {
          return SymbolsView.prototype.moveToPosition.callCount === 1;
        });
        return runs(function() {
          return expect(editor.getCursorBufferPosition()).toEqual([2, 0]);
        });
      });
      it("displays matches when more than one exists and opens the selected match", function() {
        waitsForPromise(function() {
          return atom.workspace.open(directory.resolve("tagged.js"));
        });
        runs(function() {
          editor = atom.workspace.getActiveTextEditor();
          editor.setCursorBufferPosition([8, 14]);
          return atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
        });
        waitsFor(function() {
          return $(getWorkspaceView()).find('.symbols-view').find('li').length > 0;
        });
        runs(function() {
          symbolsView = $(getWorkspaceView()).find('.symbols-view').view();
          expect(symbolsView.list.children('li').length).toBe(2);
          expect(symbolsView).toBeVisible();
          spyOn(SymbolsView.prototype, "moveToPosition").andCallThrough();
          return symbolsView.confirmed(symbolsView.items[0]);
        });
        waitsFor(function() {
          return SymbolsView.prototype.moveToPosition.callCount === 1;
        });
        return runs(function() {
          expect(atom.workspace.getActiveTextEditor().getPath()).toBe(directory.resolve("tagged-duplicate.js"));
          return expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([0, 4]);
        });
      });
      it("includes ? and ! characters in ruby symbols", function() {
        atom.project.setPaths([temp.mkdirSync("atom-symbols-view-ruby-")]);
        fs.copySync(path.join(__dirname, 'fixtures', 'ruby'), atom.project.getPaths()[0]);
        waitsForPromise(function() {
          return atom.packages.activatePackage('language-ruby');
        });
        waitsForPromise(function() {
          return atom.workspace.open('file1.rb');
        });
        runs(function() {
          spyOn(SymbolsView.prototype, "moveToPosition").andCallThrough();
          atom.workspace.getActiveTextEditor().setCursorBufferPosition([13, 4]);
          return atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
        });
        waitsForPromise(function() {
          return activationPromise;
        });
        waitsFor(function() {
          return SymbolsView.prototype.moveToPosition.callCount === 1;
        });
        runs(function() {
          expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([5, 2]);
          SymbolsView.prototype.moveToPosition.reset();
          atom.workspace.getActiveTextEditor().setCursorBufferPosition([14, 2]);
          return atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
        });
        waitsFor(function() {
          return SymbolsView.prototype.moveToPosition.callCount === 1;
        });
        runs(function() {
          expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([9, 2]);
          SymbolsView.prototype.moveToPosition.reset();
          atom.workspace.getActiveTextEditor().setCursorBufferPosition([15, 5]);
          return atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
        });
        waitsFor(function() {
          return SymbolsView.prototype.moveToPosition.callCount === 1;
        });
        return runs(function() {
          return expect(atom.workspace.getActiveTextEditor().getCursorBufferPosition()).toEqual([1, 2]);
        });
      });
      describe("return from declaration", function() {
        it("doesn't do anything when no go-to have been triggered", function() {
          waitsForPromise(function() {
            return atom.workspace.open(directory.resolve("tagged.js"));
          });
          runs(function() {
            editor = atom.workspace.getActiveTextEditor();
            editor.setCursorBufferPosition([6, 0]);
            return atom.commands.dispatch(getEditorView(), 'symbols-view:return-from-declaration');
          });
          waitsForPromise(function() {
            return activationPromise;
          });
          return runs(function() {
            return expect(editor.getCursorBufferPosition()).toEqual([6, 0]);
          });
        });
        return it("returns to previous row and column", function() {
          waitsForPromise(function() {
            return atom.workspace.open(directory.resolve("tagged.js"));
          });
          runs(function() {
            editor = atom.workspace.getActiveTextEditor();
            editor.setCursorBufferPosition([6, 24]);
            spyOn(SymbolsView.prototype, "moveToPosition").andCallThrough();
            return atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
          });
          waitsForPromise(function() {
            return activationPromise;
          });
          waitsFor(function() {
            return SymbolsView.prototype.moveToPosition.callCount === 1;
          });
          runs(function() {
            expect(editor.getCursorBufferPosition()).toEqual([2, 0]);
            return atom.commands.dispatch(getEditorView(), 'symbols-view:return-from-declaration');
          });
          waitsFor(function() {
            return SymbolsView.prototype.moveToPosition.callCount === 2;
          });
          return runs(function() {
            return expect(editor.getCursorBufferPosition()).toEqual([6, 24]);
          });
        });
      });
      return describe("when the tag is in a file that doesn't exist", function() {
        return it("doesn't display the tag", function() {
          fs.removeSync(directory.resolve("tagged-duplicate.js"));
          waitsForPromise(function() {
            return atom.workspace.open(directory.resolve("tagged.js"));
          });
          runs(function() {
            editor = atom.workspace.getActiveTextEditor();
            editor.setCursorBufferPosition([8, 14]);
            spyOn(SymbolsView.prototype, "moveToPosition").andCallThrough();
            return atom.commands.dispatch(getEditorView(), 'symbols-view:go-to-declaration');
          });
          waitsFor(function() {
            return SymbolsView.prototype.moveToPosition.callCount === 1;
          });
          return runs(function() {
            return expect(editor.getCursorBufferPosition()).toEqual([8, 0]);
          });
        });
      });
    });
    describe("project symbols", function() {
      it("displays all tags", function() {
        jasmine.unspy(window, 'setTimeout');
        waitsForPromise(function() {
          return atom.workspace.open(directory.resolve("tagged.js"));
        });
        runs(function() {
          expect($(getWorkspaceView()).find('.symbols-view')).not.toExist();
          return atom.commands.dispatch(getWorkspaceView(), "symbols-view:toggle-project-symbols");
        });
        waitsForPromise(function() {
          return activationPromise;
        });
        runs(function() {
          symbolsView = $(getWorkspaceView()).find('.symbols-view').view();
          return expect(symbolsView.loading).toBeVisible();
        });
        waitsFor(function() {
          return symbolsView.list.children('li').length > 0;
        });
        runs(function() {
          var directoryBasename;
          directoryBasename = path.basename(directory.getPath());
          expect(symbolsView.loading).toBeEmpty();
          expect($(getWorkspaceView()).find('.symbols-view')).toExist();
          expect(symbolsView.list.children('li').length).toBe(4);
          expect(symbolsView.list.children('li:first').find('.primary-line')).toHaveText('callMeMaybe');
          expect(symbolsView.list.children('li:first').find('.secondary-line')).toHaveText(path.join(directoryBasename, 'tagged.js'));
          expect(symbolsView.list.children('li:last').find('.primary-line')).toHaveText('thisIsCrazy');
          expect(symbolsView.list.children('li:last').find('.secondary-line')).toHaveText(path.join(directoryBasename, 'tagged.js'));
          expect(symbolsView.error).not.toBeVisible();
          atom.commands.dispatch(getWorkspaceView(), "symbols-view:toggle-project-symbols");
          return fs.removeSync(directory.resolve('tags'));
        });
        waitsFor(function() {
          return symbolsView.reloadTags;
        });
        runs(function() {
          return atom.commands.dispatch(getWorkspaceView(), "symbols-view:toggle-project-symbols");
        });
        waitsFor(function() {
          return symbolsView.error.text().length > 0;
        });
        return runs(function() {
          return expect(symbolsView.list.children('li').length).toBe(0);
        });
      });
      describe("when there is only one project", function() {
        beforeEach(function() {
          return atom.project.setPaths([directory.getPath()]);
        });
        return it("does not include the root directory's name when displaying the tag's filename", function() {
          jasmine.unspy(window, 'setTimeout');
          waitsForPromise(function() {
            return atom.workspace.open(directory.resolve("tagged.js"));
          });
          runs(function() {
            expect($(getWorkspaceView()).find('.symbols-view')).not.toExist();
            return atom.commands.dispatch(getWorkspaceView(), "symbols-view:toggle-project-symbols");
          });
          waitsForPromise(function() {
            return activationPromise;
          });
          runs(function() {
            return symbolsView = $(getWorkspaceView()).find('.symbols-view').view();
          });
          waitsFor(function() {
            return symbolsView.list.children('li').length > 0;
          });
          return runs(function() {
            expect(symbolsView.list.children('li:first').find('.primary-line')).toHaveText('callMeMaybe');
            return expect(symbolsView.list.children('li:first').find('.secondary-line')).toHaveText('tagged.js');
          });
        });
      });
      return describe("when selecting a tag", function() {
        return describe("when the file doesn't exist", function() {
          beforeEach(function() {
            return fs.removeSync(directory.resolve("tagged.js"));
          });
          return it("doesn't open the editor", function() {
            atom.commands.dispatch(getWorkspaceView(), "symbols-view:toggle-project-symbols");
            waitsForPromise(function() {
              return activationPromise;
            });
            runs(function() {
              return symbolsView = $(getWorkspaceView()).find('.symbols-view').view();
            });
            waitsFor(function() {
              return symbolsView.list.children('li').length > 0;
            });
            return runs(function() {
              spyOn(atom.workspace, 'open').andCallThrough();
              symbolsView.list.children('li:first').mousedown().mouseup();
              expect(atom.workspace.open).not.toHaveBeenCalled();
              return expect(symbolsView.error.text().length).toBeGreaterThan(0);
            });
          });
        });
      });
    });
    return describe("when useEditorGrammarAsCtagsLanguage is set to true", function() {
      return it("uses the language associated with the editor's grammar", function() {
        atom.config.set('symbols-view.useEditorGrammarAsCtagsLanguage', true);
        waitsForPromise(function() {
          return atom.packages.activatePackage('language-javascript');
        });
        waitsForPromise(function() {
          return atom.workspace.open('sample.javascript');
        });
        runs(function() {
          atom.workspace.getActiveTextEditor().setText("var test = function() {}");
          atom.workspace.getActiveTextEditor().save();
          return atom.commands.dispatch(getEditorView(), "symbols-view:toggle-file-symbols");
        });
        waitsForPromise(function() {
          return activationPromise;
        });
        waitsFor(function() {
          return $(getWorkspaceView()).find('.symbols-view').view().error.isVisible();
        });
        runs(function() {
          atom.commands.dispatch(getEditorView(), "symbols-view:toggle-file-symbols");
          atom.workspace.getActiveTextEditor().setGrammar(atom.grammars.grammarForScopeName('source.js'));
          atom.commands.dispatch(getEditorView(), "symbols-view:toggle-file-symbols");
          symbolsView = $(getWorkspaceView()).find('.symbols-view').view();
          return expect(symbolsView.loading).toBeVisible();
        });
        waitsFor(function() {
          return symbolsView.list.children('li').length === 1;
        });
        return runs(function() {
          expect(symbolsView.loading).toBeEmpty();
          expect($(getWorkspaceView()).find('.symbols-view')).toExist();
          expect(symbolsView.list.children('li:first').find('.primary-line')).toHaveText('test');
          return expect(symbolsView.list.children('li:first').find('.secondary-line')).toHaveText('Line 1');
        });
      });
    });
  });

}).call(this);
