'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /*global document, json */

var _EditorUtils = require('../modules/EditorUtils');

var _EditorUtils2 = _interopRequireDefault(_EditorUtils);

var _EditorJson = require('../modules/EditorJson');

var _EditorJson2 = _interopRequireDefault(_EditorJson);

var _iframe = require('../utils/iframe');

var _handlebars = require('handlebars');

var _handlebars2 = _interopRequireDefault(_handlebars);

var _nanoajax = require('nanoajax');

var _nanoajax2 = _interopRequireDefault(_nanoajax);

var _on = require('on');

var _on2 = _interopRequireDefault(_on);

var _qs = require('qs');

var _qs2 = _interopRequireDefault(_qs);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var EditorAutocomplete = function () {
  function EditorAutocomplete() {
    _classCallCheck(this, EditorAutocomplete);

    this._ajax = _nanoajax2.default.ajax;
    this._json = _EditorJson2.default.instance;
    this.onReload = (0, _on2.default)(this);
    this._previousValue = '';

    this._handleKeyUp = this._keyUp.bind(this);
    this._handleKeyDown = this._keyDown.bind(this);
    this._handleFocus = this._focus.bind(this);
    this._handleBlur = this._blur.bind(this);
    this._handleRemove = this._remove.bind(this);
    this._handleDocumentClick = this._documentClick.bind(this);
    this._handleSelectValue = this._selectValue.bind(this);
    this._handleRefresh = this._refresh.bind(this);

    this._autocompletesRemove = [].slice.call(document.querySelectorAll('[data-autocomplete-remove=true]'));
    this._autocompletes = [].slice.call(document.querySelectorAll('[data-autocomplete=true]'));
    this._autocompletesRefresh = [].slice.call(document.querySelectorAll('[data-autocomplete-refresh=true]'));

    this._currentInput = null;
    this._divWrapper = document.createElement('div');
    this._divWrapper.classList.add('autocomplete-wrapper');

    this._visible = false;

    this.rebind();
  }

  _createClass(EditorAutocomplete, [{
    key: 'rebind',
    value: function rebind() {
      var _this = this;

      document.body.removeEventListener('mouseup', this._handleDocumentClick);
      document.body.addEventListener('mouseup', this._handleDocumentClick);

      Array.prototype.forEach.call(this._autocompletesRemove, function (autocompleteRemove) {
        autocompleteRemove.addEventListener('click', _this._handleRemove);
      });

      Array.prototype.forEach.call(this._autocompletesRefresh, function (autocompletesRefresh) {
        autocompletesRefresh.removeEventListener('click', _this._handleRefresh);
        autocompletesRefresh.addEventListener('click', _this._handleRefresh);
      });

      Array.prototype.forEach.call(this._autocompletes, function (autocomplete) {
        document.body.removeEventListener('keydown', _this._handleKeyDown);
        document.body.addEventListener('keydown', _this._handleKeyDown);
        autocomplete.removeEventListener('keyup', _this._handleKeyUp);
        autocomplete.addEventListener('keyup', _this._handleKeyUp);
        autocomplete.removeEventListener('focus', _this._handleFocus);
        autocomplete.addEventListener('focus', _this._handleFocus);
        autocomplete.removeEventListener('blur', _this._handleBlur);
        autocomplete.addEventListener('blur', _this._handleBlur);
      });
    }
  }, {
    key: '_saveData',
    value: function _saveData() {
      var _this2 = this;

      var id = this._currentInput.getAttribute('id');
      var nodeComments = (0, _iframe.IframeCommentNode)('#page-template', id);
      var maxLength = this._currentInput.getAttribute('data-maxlength');

      if (typeof maxLength !== 'undefined' && maxLength !== null && maxLength !== '') {
        maxLength = parseInt(maxLength);
        var countLength = [].slice.call(this._currentInput.parentNode.querySelectorAll('.autocomplete-result-wrapper .autocomplete-result')).length;
        if (countLength === maxLength) {
          this._currentInput.value = '';
          this._divWrapper.parentNode.removeChild(this._divWrapper);
          this._currentInput.setAttribute('disabled', 'disabled');
        } else {
          this._currentInput.removeAttribute('disabled');
        }
      }

      var results = [].slice.call(this._currentInput.parentNode.querySelectorAll('.autocomplete-result-wrapper .autocomplete-result'));
      var json = this._json.data;

      json[id] = [];
      Array.prototype.forEach.call(results, function (result) {
        var value = result.getAttribute('value');
        if (value !== '') {
          if (value.indexOf('{') > -1 || value.indexOf('[') > -1) {
            json[id].push(JSON.parse(value));
          } else {
            json[id].push(value);
          }
        }
      });

      this._json.data = json;

      if (typeof nodeComments !== 'undefined' && nodeComments !== null && nodeComments.length > 0) {

        try {
          Array.prototype.forEach.call(nodeComments, function (nodeComment) {
            var blockHtml = unescape(nodeComment.textContent.replace(/\[\[([\S\s]*?)\]\]/, '')).replace(/\[0\]-/g, '[0]-');

            // var blockHtml = unescape(blockContent.innerHTML).replace(/\[0\]-/g, '[0]-')
            var template = _handlebars2.default.compile(blockHtml, { noEscape: true });
            var compiled = template(_this2._json.data);

            nodeComment.parentNode.innerHTML = compiled + ('<!-- ' + nodeComment.textContent + ' -->');
          });
        } catch (e) {
          console.log(e);
        }
      } else if (typeof id !== 'undefined' && id !== null) {
        if (this._currentInput.getAttribute('visible') === true) {
          var nodes = _EditorUtils2.default.getNode(attr);
          Array.prototype.forEach.call(nodes, function (node) {
            _EditorUtils2.default.formToHtml(node, _this2._currentInput);
          });
        }
      }

      this.onReload._fire();
    }
  }, {
    key: '_documentClick',
    value: function _documentClick() {
      if (this._visible && !this._canSelect) {
        if (typeof this._divWrapper.parentNode !== 'undefined' && this._divWrapper.parentNode !== null) {
          this._hide();
        }
      }
    }
  }, {
    key: '_add',
    value: function _add(display, value, json, autocompleteResultWrapper) {
      var div = document.createElement('div');
      div.classList.add('autocomplete-result');
      div.setAttribute('data-parent-id', this._currentInput.getAttribute('data-id'));
      div.setAttribute('value', value.replace(/&quote;/g, '\''));
      div.innerHTML = this._prepareDisplay(json, display);

      var remove = document.createElement('span');
      remove.classList.add('glyphicon', 'glyphicon-remove');
      remove.setAttribute('data-autocomplete-remove', 'true');
      remove.addEventListener('click', this._handleRemove);
      div.appendChild(remove);

      autocompleteResultWrapper.appendChild(div);
    }
  }, {
    key: '_select',
    value: function _select(target) {
      var json = target.getAttribute('data-value').replace(/&quote;/g, '\'');
      if (json.indexOf('{') > -1) {
        json = JSON.parse(json);
      }
      var maxLength = this._currentInput.getAttribute('data-maxlength');
      if (typeof maxLength !== 'undefined' && maxLength !== null && maxLength !== '') {
        maxLength = parseInt(maxLength);
        var countLength = [].slice.call(this._currentInput.parentNode.querySelectorAll('.autocomplete-result-wrapper .autocomplete-result')).length;
        if (countLength + 1 > maxLength) {
          return;
        }
      }

      this._add(this._currentInput.getAttribute('data-display'), target.getAttribute('data-value'), json, this._divWrapper.parentNode.querySelector('.autocomplete-result-wrapper'));
      this._saveData();
    }
  }, {
    key: '_selectValue',
    value: function _selectValue(e) {
      this._select(e.currentTarget);
    }
  }, {
    key: '_showAutocomplete',
    value: function _showAutocomplete(obj, target, val) {
      var _this3 = this;

      var first = true;
      var str = target.getAttribute('data-display');
      this._divWrapper.innerHTML = '';
      this.result = [];
      var keys = this._getKeys(str);
      var key = keys[0];
      this._find(obj, key);
      Array.prototype.forEach.call(this.result, function (o) {

        var displayName = _this3._prepareDisplay(o, str, keys);
        if (displayName.toLowerCase().indexOf(val.toLowerCase()) > -1) {
          var div = document.createElement('div');
          div.addEventListener('mousedown', _this3._handleSelectValue);
          div.setAttribute('data-value', (typeof o === 'undefined' ? 'undefined' : _typeof(o)) == 'object' ? JSON.stringify(o) : o);
          div.setAttribute('data-display', displayName);
          if (first) {
            div.classList.add('selected');
          }
          first = false;
          div.innerHTML = displayName.replace(new RegExp('(' + val + ')', 'i'), '<span class="select">$1</span>');
          _this3._divWrapper.appendChild(div);
        }
      });

      this._show(target);
    }

    /**
     * add in array the object containing the object path if it exists in obj
     * @param  {Object}  obj  json object
     * @param  {string}  path the path to object (dot notation)
     */

  }, {
    key: '_find',
    value: function _find(obj, path) {
      if (path == null) {
        this.result = obj;
      } else {
        if (this._has(obj, path)) {
          this.result.push(obj);
        }
        for (var key in obj) {
          if (obj.hasOwnProperty(key)) {
            if ('object' == _typeof(obj[key]) && !this._has(obj[key], path)) {
              this._find(obj[key], path);
            } else if (this._has(obj[key], path)) {
              this.result.push(obj[key]);
            }
          }
        }
      }
    }

    /**
     * return true if the object path exist in obj
     * @param  {Object}  obj  json object
     * @param  {string}  path the path to object (dot notation)
     * @return {Boolean}      is the path found in obj
     */

  }, {
    key: '_has',
    value: function _has(obj, path) {
      return path.split('.').every(function (x) {
        if ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) != 'object' || obj === null || typeof obj[x] == 'undefined') return false;
        obj = obj[x];
        return true;
      });
    }

    /**
     * return the value from a json obj of a nested attribute
     * @param  {Object} obj  the json object
     * @param  {string} path the path to object (dot notation)
     * @return {[type]}      the object containing the path object or undefined
     */

  }, {
    key: '_get',
    value: function _get(obj, path) {
      return path.split('.').reduce(function (prev, curr) {
        return prev ? prev[curr] : undefined;
      }, obj || this);
    }

    /**
     * replace the variables in str by values from obj
     * corresponding to keys
     * @param  {Object} obj    the json object
     * @param  {string} str    the string
     * @return {string}        the string with values
     */

  }, {
    key: '_prepareDisplay',
    value: function _prepareDisplay(obj) {
      var _this4 = this;

      var str = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;

      var keys = this._getKeys(str);
      Array.prototype.forEach.call(keys, function (key) {
        var val = _this4._get(obj, key);
        var pattern = new RegExp('{{' + key + '}}|' + key, 'g');
        str = str.replace(pattern, val);
      });

      if (str == null) {
        str = obj;
      }

      return str;
    }

    /**
     * return array of variables {{variable}} extracted from str
     * @param  {string} str the string containing variables
     * @return {Array}     the array of variables
     */

  }, {
    key: '_getKeys',
    value: function _getKeys(str) {
      var regex = /\{\{(.*?)\}\}/g;
      var variables = [];
      var match;

      while ((match = regex.exec(str)) !== null) {
        variables.push(match[1]);
      }

      if (variables.length == 0 && str != null) {
        variables.push(str);
      }

      return variables;
    }
  }, {
    key: '_hide',
    value: function _hide() {
      if (this._visible) {
        this._visible = false;
        this._shouldBeVisible = false;
        if (this._divWrapper != null && this._divWrapper.parentNode) {
          this._divWrapper.parentNode.removeChild(this._divWrapper);
        }
      }
    }
  }, {
    key: '_show',
    value: function _show(target) {
      if (!this._visible) {
        this._visible = true;
        this._divWrapper.style.marginTop = target.offsetHeight + 'px';
        this._divWrapper.style.width = target.offsetWidth + 'px';
        target.parentNode.insertBefore(this._divWrapper, target);
      }
    }
  }, {
    key: '_startAutocomplete',
    value: function _startAutocomplete(target) {
      var _this5 = this;

      var val = target.value.toLowerCase();
      if (val.length > 2) {
        if (this._previousValue === val) {
          this._show(target);
          return;
        } else {
          this._previousValue = val;
        }
        var dataVal = target.getAttribute('data-value').replace(/&quote;/g, '\'');

        if (dataVal.indexOf('{{') > -1) {
          var match;
          while (match = /\{\{(.*?)\}\}/.exec(dataVal)) {
            var selector = target.form.querySelector('[data-id="' + match[1] + '"]');
            if (selector != null) {
              dataVal = dataVal.replace('{{' + match[1] + '}}', selector.value);
            }
          }
        }

        if (dataVal.indexOf('http') === 0) {
          this._ajax({
            url: '' + dataVal + val,
            body: '',
            cors: true,
            method: 'get'
          }, function (code, responseText) {
            _this5._showAutocomplete(JSON.parse(responseText), target, val);
          });
        } else {
          var sources = JSON.parse(target.getAttribute('data-value').replace(/&quote;/g, '\''));
          this._showAutocomplete(sources, target, val);
        }
      } else {
        this._hide();
      }
    }
  }, {
    key: '_keyUp',
    value: function _keyUp(e) {
      if (e.keyCode !== 13) {
        this._startAutocomplete(e.currentTarget);
      }
    }
  }, {
    key: '_refresh',
    value: function _refresh(e) {
      var _this6 = this;

      var target = e.currentTarget;

      var autocompleteResultWrapper = target.parentNode.parentNode.querySelector('.autocomplete-result-wrapper');
      var autocompleteResult = autocompleteResultWrapper.querySelectorAll('.autocomplete-result');
      Array.prototype.forEach.call(autocompleteResult, function (autocompleteResult) {
        autocompleteResult.parentNode.removeChild(autocompleteResult);
      });

      var jsonPost = JSON.parse(JSON.stringify(json));
      delete jsonPost.abe_source;
      this._currentInput = target.parentNode.parentNode.querySelector('input');
      var display = target.getAttribute('data-autocomplete-data-display');
      var body = _qs2.default.stringify({
        sourceString: target.getAttribute('data-autocomplete-refresh-sourcestring'),
        prefillQuantity: target.getAttribute('data-autocomplete-refresh-prefill-quantity'),
        key: target.getAttribute('data-autocomplete-refresh-key'),
        json: jsonPost
      });

      this._ajax({
        url: '/abe/sql-request',
        body: body,
        cors: true,
        method: 'post'
      }, function (code, responseText) {
        var items = JSON.parse(responseText);
        Array.prototype.forEach.call(items, function (item) {
          this._add(display, JSON.stringify(item), item, autocompleteResultWrapper);
        }.bind(_this6));
        _this6._saveData();
      });
    }
  }, {
    key: '_keyDown',
    value: function _keyDown(e) {
      if (this._canSelect) {
        var parent = this._currentInput.parentNode.querySelector('.autocomplete-wrapper');
        if (typeof parent !== 'undefined' && parent !== null) {
          var current = this._currentInput.parentNode.querySelector('.autocomplete-wrapper .selected');

          var newSelected = null;
          var selected = document.querySelector('.autocomplete-wrapper .selected');
          switch (e.keyCode) {
            case 9:
              // tab
              this._hide();
              break;
            case 13:
              // enter
              e.preventDefault();
              if (typeof selected !== 'undefined' && selected !== null) {
                this._select(selected);
                this._hide();
              }
              break;
            case 27:
              // escape
              e.preventDefault();
              this._hide();
              break;
            case 40:
              // down
              e.preventDefault();
              if (typeof selected !== 'undefined' && selected !== null) {
                newSelected = selected.nextSibling;
                this._show(e.currentTarget);
              }
              break;
            case 38:
              // prev
              e.preventDefault();
              if (typeof selected !== 'undefined' && selected !== null) {
                newSelected = selected.previousSibling;
              }
              break;
            default:
              break;
          }

          if (typeof newSelected !== 'undefined' && newSelected !== null) {
            var scrollTopMin = parent.scrollTop;
            var scrollTopMax = parent.scrollTop + parent.offsetHeight - newSelected.offsetHeight;
            var offsetTop = newSelected.offsetTop;
            if (scrollTopMax < offsetTop) {
              parent.scrollTop = newSelected.offsetTop - parent.offsetHeight + newSelected.offsetHeight;
            } else if (scrollTopMin > offsetTop) {
              parent.scrollTop = newSelected.offsetTop;
            }
            current.classList.remove('selected');
            newSelected.classList.add('selected');
          }
        }
      }
    }
  }, {
    key: '_focus',
    value: function _focus(e) {
      this._canSelect = true;
      this._currentInput = e.currentTarget;
      this._startAutocomplete(e.currentTarget);
    }
  }, {
    key: '_blur',
    value: function _blur() {
      this._canSelect = false;
      this._currentInput = null;
      this._hide();
    }
  }, {
    key: '_remove',
    value: function _remove(e) {
      var target = e.currentTarget.parentNode;
      this._currentInput = document.querySelector('#' + target.getAttribute('data-parent-id'));
      target.parentNode.removeChild(target);
      this._saveData();
      this._currentInput = null;
    }
  }]);

  return EditorAutocomplete;
}();

exports.default = EditorAutocomplete;