(function() {
  var $$$, CompositeDisposable, FindModel, FindView, HistoryCycler, TextEditorView, View, _, _ref,
    __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; };

  _ = require('underscore-plus');

  _ref = require('atom-space-pen-views'), $$$ = _ref.$$$, View = _ref.View, TextEditorView = _ref.TextEditorView;

  CompositeDisposable = require('atom').CompositeDisposable;

  FindModel = require('./find-model');

  HistoryCycler = require('./history').HistoryCycler;

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

    function FindView() {
      this.toggleWholeWordOption = __bind(this.toggleWholeWordOption, this);
      this.toggleSelectionOption = __bind(this.toggleSelectionOption, this);
      this.toggleCaseOption = __bind(this.toggleCaseOption, this);
      this.toggleRegexOption = __bind(this.toggleRegexOption, this);
      this.setSelectionAsFindPattern = __bind(this.setSelectionAsFindPattern, this);
      this.selectAllMarkers = __bind(this.selectAllMarkers, this);
      this.selectFirstMarkerBeforeCursor = __bind(this.selectFirstMarkerBeforeCursor, this);
      this.selectFirstMarkerAfterCursor = __bind(this.selectFirstMarkerAfterCursor, this);
      this.updateResultCounter = __bind(this.updateResultCounter, this);
      this.findError = __bind(this.findError, this);
      this.markersUpdated = __bind(this.markersUpdated, this);
      this.replaceAll = __bind(this.replaceAll, this);
      this.replacePrevious = __bind(this.replacePrevious, this);
      this.replaceNext = __bind(this.replaceNext, this);
      this.findAndSelectResult = __bind(this.findAndSelectResult, this);
      this.findPrevious = __bind(this.findPrevious, this);
      this.findNext = __bind(this.findNext, this);
      this.findAll = __bind(this.findAll, this);
      this.toggleFocus = __bind(this.toggleFocus, this);
      this.focusReplaceEditor = __bind(this.focusReplaceEditor, this);
      this.focusFindEditor = __bind(this.focusFindEditor, this);
      return FindView.__super__.constructor.apply(this, arguments);
    }

    FindView.content = function() {
      return this.div({
        tabIndex: -1,
        "class": 'find-and-replace'
      }, (function(_this) {
        return function() {
          _this.header({
            "class": 'header'
          }, function() {
            _this.span({
              outlet: 'descriptionLabel',
              "class": 'header-item description'
            }, 'Find in Current Buffer');
            return _this.span({
              "class": 'header-item options-label pull-right'
            }, function() {
              _this.span('Finding with Options: ');
              return _this.span({
                outlet: 'optionsLabel',
                "class": 'options'
              });
            });
          });
          _this.section({
            "class": 'input-block find-container'
          }, function() {
            _this.div({
              "class": 'input-block-item input-block-item--flex editor-container'
            }, function() {
              _this.subview('findEditor', new TextEditorView({
                mini: true,
                placeholderText: 'Find in current buffer'
              }));
              return _this.div({
                "class": 'find-meta-container'
              }, function() {
                return _this.span({
                  outlet: 'resultCounter',
                  "class": 'text-subtle result-counter'
                }, '');
              });
            });
            return _this.div({
              "class": 'input-block-item'
            }, function() {
              _this.div({
                "class": 'btn-group btn-group-find'
              }, function() {
                return _this.button({
                  outlet: 'nextButton',
                  "class": 'btn'
                }, 'Find');
              });
              return _this.div({
                "class": 'btn-group btn-toggle btn-group-options'
              }, function() {
                _this.button({
                  outlet: 'regexOptionButton',
                  "class": 'btn'
                }, '.*');
                _this.button({
                  outlet: 'caseOptionButton',
                  "class": 'btn'
                }, 'Aa');
                _this.button({
                  outlet: 'selectionOptionButton',
                  "class": 'btn option-selection'
                }, '"');
                return _this.button({
                  outlet: 'wholeWordOptionButton',
                  "class": 'btn option-whole-word'
                }, '\\b');
              });
            });
          });
          return _this.section({
            "class": 'input-block replace-container'
          }, function() {
            _this.div({
              "class": 'input-block-item input-block-item--flex editor-container'
            }, function() {
              return _this.subview('replaceEditor', new TextEditorView({
                mini: true,
                placeholderText: 'Replace in current buffer'
              }));
            });
            return _this.div({
              "class": 'input-block-item'
            }, function() {
              _this.div({
                "class": 'btn-group btn-group-replace'
              }, function() {
                return _this.button({
                  outlet: 'replaceNextButton',
                  "class": 'btn btn-next'
                }, 'Replace');
              });
              return _this.div({
                "class": 'btn-group btn-group-replace-all'
              }, function() {
                return _this.button({
                  outlet: 'replaceAllButton',
                  "class": 'btn btn-all'
                }, 'Replace All');
              });
            });
          });
        };
      })(this));
    };

    FindView.prototype.initialize = function(findModel, _arg) {
      var findHistory, replaceHistory;
      this.findModel = findModel;
      findHistory = _arg.findHistory, replaceHistory = _arg.replaceHistory;
      this.subscriptions = new CompositeDisposable;
      this.findHistory = new HistoryCycler(this.findEditor, findHistory);
      this.replaceHistory = new HistoryCycler(this.replaceEditor, replaceHistory);
      this.handleEvents();
      this.updateOptionButtons();
      this.clearMessage();
      return this.updateOptionsLabel();
    };

    FindView.prototype.destroy = function() {
      var _ref1, _ref2;
      if ((_ref1 = this.subscriptions) != null) {
        _ref1.dispose();
      }
      return (_ref2 = this.tooltipSubscriptions) != null ? _ref2.dispose() : void 0;
    };

    FindView.prototype.setPanel = function(panel) {
      this.panel = panel;
      return this.subscriptions.add(this.panel.onDidChangeVisible((function(_this) {
        return function(visible) {
          if (visible) {
            return _this.didShow();
          } else {
            return _this.didHide();
          }
        };
      })(this)));
    };

    FindView.prototype.didShow = function() {
      var subs;
      atom.views.getView(atom.workspace).classList.add('find-visible');
      if (this.tooltipSubscriptions != null) {
        return;
      }
      this.tooltipSubscriptions = subs = new CompositeDisposable;
      subs.add(atom.tooltips.add(this.regexOptionButton, {
        title: "Use Regex",
        keyBindingCommand: 'find-and-replace:toggle-regex-option',
        keyBindingTarget: this.findEditor.element
      }));
      subs.add(atom.tooltips.add(this.caseOptionButton, {
        title: "Match Case",
        keyBindingCommand: 'find-and-replace:toggle-case-option',
        keyBindingTarget: this.findEditor.element
      }));
      subs.add(atom.tooltips.add(this.selectionOptionButton, {
        title: "Only In Selection",
        keyBindingCommand: 'find-and-replace:toggle-selection-option',
        keyBindingTarget: this.findEditor.element
      }));
      subs.add(atom.tooltips.add(this.nextButton, {
        title: "Find Next",
        keyBindingCommand: 'find-and-replace:find-next',
        keyBindingTarget: this.findEditor.element
      }));
      subs.add(atom.tooltips.add(this.replaceNextButton, {
        title: "Replace Next",
        keyBindingCommand: 'find-and-replace:replace-next',
        keyBindingTarget: this.replaceEditor.element
      }));
      return subs.add(atom.tooltips.add(this.replaceAllButton, {
        title: "Replace All",
        keyBindingCommand: 'find-and-replace:replace-all',
        keyBindingTarget: this.replaceEditor.element
      }));
    };

    FindView.prototype.didHide = function() {
      var workspaceElement;
      this.hideAllTooltips();
      workspaceElement = atom.views.getView(atom.workspace);
      workspaceElement.focus();
      return workspaceElement.classList.remove('find-visible');
    };

    FindView.prototype.hideAllTooltips = function() {
      this.tooltipSubscriptions.dispose();
      return this.tooltipSubscriptions = null;
    };

    FindView.prototype.handleEvents = function() {
      this.handleFindEvents();
      this.handleReplaceEvents();
      this.subscriptions.add(atom.commands.add(this.findEditor.element, {
        'core:confirm': (function(_this) {
          return function() {
            return _this.confirm();
          };
        })(this),
        'find-and-replace:confirm': (function(_this) {
          return function() {
            return _this.confirm();
          };
        })(this),
        'find-and-replace:show-previous': (function(_this) {
          return function() {
            return _this.showPrevious();
          };
        })(this),
        'find-and-replace:find-all': (function(_this) {
          return function() {
            return _this.findAll();
          };
        })(this)
      }));
      this.subscriptions.add(atom.commands.add(this.replaceEditor.element, {
        'core:confirm': (function(_this) {
          return function() {
            return _this.replaceNext();
          };
        })(this)
      }));
      this.subscriptions.add(atom.commands.add(this.element, {
        'core:close': (function(_this) {
          return function() {
            var _ref1;
            return (_ref1 = _this.panel) != null ? _ref1.hide() : void 0;
          };
        })(this),
        'core:cancel': (function(_this) {
          return function() {
            var _ref1;
            return (_ref1 = _this.panel) != null ? _ref1.hide() : void 0;
          };
        })(this),
        'find-and-replace:focus-next': this.toggleFocus,
        'find-and-replace:focus-previous': this.toggleFocus,
        'find-and-replace:toggle-regex-option': this.toggleRegexOption,
        'find-and-replace:toggle-case-option': this.toggleCaseOption,
        'find-and-replace:toggle-selection-option': this.toggleSelectionOption,
        'find-and-replace:toggle-whole-word-option': this.toggleWholeWordOption
      }));
      this.subscriptions.add(this.findModel.onDidUpdate(this.markersUpdated));
      this.subscriptions.add(this.findModel.onDidError(this.findError));
      this.subscriptions.add(this.findModel.onDidChangeCurrentResult(this.updateResultCounter));
      this.regexOptionButton.on('click', this.toggleRegexOption);
      this.caseOptionButton.on('click', this.toggleCaseOption);
      this.selectionOptionButton.on('click', this.toggleSelectionOption);
      this.wholeWordOptionButton.on('click', this.toggleWholeWordOption);
      this.on('focus', (function(_this) {
        return function() {
          return _this.findEditor.focus();
        };
      })(this));
      return this.find('button').on('click', (function(_this) {
        return function() {
          var workspaceElement;
          workspaceElement = atom.views.getView(atom.workspace);
          return workspaceElement.focus();
        };
      })(this));
    };

    FindView.prototype.handleFindEvents = function() {
      this.findEditor.getModel().onDidStopChanging((function(_this) {
        return function() {
          return _this.liveSearch();
        };
      })(this));
      this.nextButton.on('click', (function(_this) {
        return function() {
          return _this.findNext({
            focusEditorAfter: true
          });
        };
      })(this));
      return this.subscriptions.add(atom.commands.add('atom-workspace', {
        'find-and-replace:find-next': (function(_this) {
          return function() {
            return _this.findNext({
              focusEditorAfter: true
            });
          };
        })(this),
        'find-and-replace:find-previous': (function(_this) {
          return function() {
            return _this.findPrevious({
              focusEditorAfter: true
            });
          };
        })(this),
        'find-and-replace:use-selection-as-find-pattern': this.setSelectionAsFindPattern
      }));
    };

    FindView.prototype.handleReplaceEvents = function() {
      this.replaceNextButton.on('click', this.replaceNext);
      this.replaceAllButton.on('click', this.replaceAll);
      return this.subscriptions.add(atom.commands.add('atom-workspace', {
        'find-and-replace:replace-previous': this.replacePrevious,
        'find-and-replace:replace-next': this.replaceNext,
        'find-and-replace:replace-all': this.replaceAll
      }));
    };

    FindView.prototype.focusFindEditor = function() {
      var selectedText, _ref1;
      selectedText = (_ref1 = atom.workspace.getActiveTextEditor()) != null ? typeof _ref1.getSelectedText === "function" ? _ref1.getSelectedText() : void 0 : void 0;
      if (selectedText && selectedText.indexOf('\n') < 0) {
        this.findEditor.setText(selectedText);
      }
      this.findEditor.focus();
      return this.findEditor.getModel().selectAll();
    };

    FindView.prototype.focusReplaceEditor = function() {
      this.replaceEditor.focus();
      return this.replaceEditor.getModel().selectAll();
    };

    FindView.prototype.toggleFocus = function() {
      if (this.findEditor.hasClass('is-focused')) {
        return this.replaceEditor.focus();
      } else {
        return this.findEditor.focus();
      }
    };

    FindView.prototype.confirm = function() {
      return this.findNext({
        focusEditorAfter: atom.config.get('find-and-replace.focusEditorAfterSearch')
      });
    };

    FindView.prototype.showPrevious = function() {
      return this.findPrevious({
        focusEditorAfter: atom.config.get('find-and-replace.focusEditorAfterSearch')
      });
    };

    FindView.prototype.liveSearch = function() {
      var pattern;
      pattern = this.findEditor.getText();
      return this.updateModel({
        pattern: pattern
      });
    };

    FindView.prototype.findAll = function(options) {
      if (options == null) {
        options = {
          focusEditorAfter: true
        };
      }
      return this.findAndSelectResult(this.selectAllMarkers, options);
    };

    FindView.prototype.findNext = function(options) {
      if (options == null) {
        options = {
          focusEditorAfter: false
        };
      }
      return this.findAndSelectResult(this.selectFirstMarkerAfterCursor, options);
    };

    FindView.prototype.findPrevious = function(options) {
      if (options == null) {
        options = {
          focusEditorAfter: false
        };
      }
      return this.findAndSelectResult(this.selectFirstMarkerBeforeCursor, options);
    };

    FindView.prototype.findAndSelectResult = function(selectFunction, _arg) {
      var fieldToFocus, focusEditorAfter, pattern, workspaceElement;
      focusEditorAfter = _arg.focusEditorAfter, fieldToFocus = _arg.fieldToFocus;
      pattern = this.findEditor.getText();
      this.updateModel({
        pattern: pattern
      });
      this.findHistory.store();
      if (this.markers.length === 0) {
        return atom.beep();
      } else {
        selectFunction();
        if (fieldToFocus) {
          return fieldToFocus.focus();
        } else if (focusEditorAfter) {
          workspaceElement = atom.views.getView(atom.workspace);
          return workspaceElement.focus();
        } else {
          return this.findEditor.focus();
        }
      }
    };

    FindView.prototype.replaceNext = function() {
      return this.replace('findNext', 'firstMarkerIndexAfterCursor');
    };

    FindView.prototype.replacePrevious = function() {
      return this.replace('findPrevious', 'firstMarkerIndexBeforeCursor');
    };

    FindView.prototype.replace = function(nextOrPreviousFn, nextIndexFn) {
      var currentMarker, markerIndex, pattern;
      pattern = this.findEditor.getText();
      this.updateModel({
        pattern: pattern
      });
      this.findHistory.store();
      this.replaceHistory.store();
      if (this.markers.length === 0) {
        return atom.beep();
      } else {
        if (!(currentMarker = this.findModel.currentResultMarker)) {
          markerIndex = this[nextIndexFn]();
          currentMarker = this.markers[markerIndex];
        }
        this.findModel.replace([currentMarker], this.replaceEditor.getText());
        return this[nextOrPreviousFn]({
          fieldToFocus: this.replaceEditor
        });
      }
    };

    FindView.prototype.replaceAll = function() {
      this.updateModel({
        pattern: this.findEditor.getText()
      });
      this.replaceHistory.store();
      this.findHistory.store();
      return this.findModel.replace(this.markers, this.replaceEditor.getText());
    };

    FindView.prototype.markersUpdated = function(markers) {
      var results, resultsStr;
      this.markers = markers;
      this.findError = null;
      this.updateOptionButtons();
      this.updateResultCounter();
      if (this.findModel.pattern) {
        results = this.markers.length;
        resultsStr = results ? _.pluralize(results, 'result') : 'No results';
        this.setInfoMessage("" + resultsStr + " found for '" + this.findModel.pattern + "'");
      } else {
        this.clearMessage();
      }
      if (this.findModel.pattern !== this.findEditor.getText()) {
        return this.findEditor.setText(this.findModel.pattern);
      }
    };

    FindView.prototype.findError = function(error) {
      return this.setErrorMessage(error.message);
    };

    FindView.prototype.updateModel = function(options) {
      return this.findModel.update(options);
    };

    FindView.prototype.updateResultCounter = function() {
      var index, text;
      if (this.findModel.currentResultMarker && (index = this.markers.indexOf(this.findModel.currentResultMarker)) > -1) {
        text = "" + (index + 1) + " of " + this.markers.length;
      } else {
        if ((this.markers == null) || this.markers.length === 0) {
          text = "no results";
        } else if (this.markers.length === 1) {
          text = "1 found";
        } else {
          text = "" + this.markers.length + " found";
        }
      }
      return this.resultCounter.text(text);
    };

    FindView.prototype.setInfoMessage = function(infoMessage) {
      return this.descriptionLabel.text(infoMessage).removeClass('text-error');
    };

    FindView.prototype.setErrorMessage = function(errorMessage) {
      return this.descriptionLabel.text(errorMessage).addClass('text-error');
    };

    FindView.prototype.clearMessage = function() {
      return this.descriptionLabel.html('Find in Current Buffer <span class="subtle-info-message">Close this panel with the <span class="highlight">esc</span> key</span>').removeClass('text-error');
    };

    FindView.prototype.selectFirstMarkerAfterCursor = function() {
      var markerIndex;
      markerIndex = this.firstMarkerIndexAfterCursor();
      return this.selectMarkerAtIndex(markerIndex);
    };

    FindView.prototype.firstMarkerIndexAfterCursor = function() {
      var editor, end, index, marker, markerStartPosition, selection, start, _i, _len, _ref1, _ref2;
      editor = this.findModel.getEditor();
      if (!editor) {
        return -1;
      }
      selection = editor.getLastSelection();
      _ref1 = selection.getBufferRange(), start = _ref1.start, end = _ref1.end;
      if (selection.isReversed()) {
        start = end;
      }
      _ref2 = this.markers;
      for (index = _i = 0, _len = _ref2.length; _i < _len; index = ++_i) {
        marker = _ref2[index];
        markerStartPosition = marker.bufferMarker.getStartPosition();
        if (markerStartPosition.isGreaterThan(start)) {
          return index;
        }
      }
      return 0;
    };

    FindView.prototype.selectFirstMarkerBeforeCursor = function() {
      var markerIndex;
      markerIndex = this.firstMarkerIndexBeforeCursor();
      return this.selectMarkerAtIndex(markerIndex);
    };

    FindView.prototype.firstMarkerIndexBeforeCursor = function() {
      var editor, end, index, marker, markerEndPosition, selection, start, _i, _ref1, _ref2;
      editor = this.findModel.getEditor();
      if (!editor) {
        return -1;
      }
      selection = this.findModel.getEditor().getLastSelection();
      _ref1 = selection.getBufferRange(), start = _ref1.start, end = _ref1.end;
      if (selection.isReversed()) {
        start = end;
      }
      _ref2 = this.markers;
      for (index = _i = _ref2.length - 1; _i >= 0; index = _i += -1) {
        marker = _ref2[index];
        markerEndPosition = marker.bufferMarker.getEndPosition();
        if (markerEndPosition.isLessThan(start)) {
          return index;
        }
      }
      return this.markers.length - 1;
    };

    FindView.prototype.selectAllMarkers = function() {
      var editor, marker, ranges, scrollMarker, _ref1;
      if (!(((_ref1 = this.markers) != null ? _ref1.length : void 0) > 0)) {
        return;
      }
      ranges = (function() {
        var _i, _len, _ref2, _results;
        _ref2 = this.markers;
        _results = [];
        for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
          marker = _ref2[_i];
          _results.push(marker.getBufferRange());
        }
        return _results;
      }).call(this);
      scrollMarker = this.markers[this.firstMarkerIndexAfterCursor()];
      editor = this.findModel.getEditor();
      editor.setSelectedBufferRanges(ranges, {
        flash: true
      });
      return editor.scrollToBufferPosition(scrollMarker.getStartBufferPosition(), {
        center: true
      });
    };

    FindView.prototype.selectMarkerAtIndex = function(markerIndex) {
      var editor, marker, _ref1;
      if (!(((_ref1 = this.markers) != null ? _ref1.length : void 0) > 0)) {
        return;
      }
      if (marker = this.markers[markerIndex]) {
        editor = this.findModel.getEditor();
        editor.setSelectedBufferRange(marker.getBufferRange(), {
          flash: true
        });
        return editor.scrollToCursorPosition({
          center: true
        });
      }
    };

    FindView.prototype.setSelectionAsFindPattern = function() {
      var pattern;
      pattern = this.findModel.getEditor().getSelectedText();
      return this.updateModel({
        pattern: pattern
      });
    };

    FindView.prototype.updateOptionsLabel = function() {
      var label;
      label = [];
      if (this.findModel.useRegex) {
        label.push('Regex');
      }
      if (this.findModel.caseSensitive) {
        label.push('Case Sensitive');
      } else {
        label.push('Case Insensitive');
      }
      if (this.findModel.inCurrentSelection) {
        label.push('Within Current Selection');
      }
      if (this.findModel.wholeWord) {
        label.push('Whole Word');
      }
      return this.optionsLabel.text(label.join(', '));
    };

    FindView.prototype.toggleRegexOption = function() {
      this.updateModel({
        pattern: this.findEditor.getText(),
        useRegex: !this.findModel.useRegex
      });
      this.selectFirstMarkerAfterCursor();
      return this.updateOptionsLabel();
    };

    FindView.prototype.toggleCaseOption = function() {
      this.updateModel({
        pattern: this.findEditor.getText(),
        caseSensitive: !this.findModel.caseSensitive
      });
      this.selectFirstMarkerAfterCursor();
      return this.updateOptionsLabel();
    };

    FindView.prototype.toggleSelectionOption = function() {
      this.updateModel({
        pattern: this.findEditor.getText(),
        inCurrentSelection: !this.findModel.inCurrentSelection
      });
      this.selectFirstMarkerAfterCursor();
      return this.updateOptionsLabel();
    };

    FindView.prototype.toggleWholeWordOption = function() {
      this.updateModel({
        pattern: this.findEditor.getText(),
        wholeWord: !this.findModel.wholeWord
      });
      this.selectFirstMarkerAfterCursor();
      return this.updateOptionsLabel();
    };

    FindView.prototype.setOptionButtonState = function(optionButton, selected) {
      if (selected) {
        return optionButton.addClass('selected');
      } else {
        return optionButton.removeClass('selected');
      }
    };

    FindView.prototype.updateOptionButtons = function() {
      this.setOptionButtonState(this.regexOptionButton, this.findModel.useRegex);
      this.setOptionButtonState(this.caseOptionButton, this.findModel.caseSensitive);
      this.setOptionButtonState(this.selectionOptionButton, this.findModel.inCurrentSelection);
      return this.setOptionButtonState(this.wholeWordOptionButton, this.findModel.wholeWord);
    };

    return FindView;

  })(View);

}).call(this);
