(function() {
  var $, $$, CompositeDisposable, SettingsPanel, TextEditorView, View, appendArray, appendCheckbox, appendColor, appendEditor, appendObject, appendOptions, appendSetting, getSettingDescription, getSettingTitle, isEditableArray, _, _ref,
    __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; };

  CompositeDisposable = require('atom').CompositeDisposable;

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

  _ = require('underscore-plus');

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

    function SettingsPanel() {
      return SettingsPanel.__super__.constructor.apply(this, arguments);
    }

    SettingsPanel.content = function() {
      return this.section({
        "class": 'section settings-panel'
      });
    };

    SettingsPanel.prototype.initialize = function(namespace, options) {
      var name, scopedSettings, settings, _i, _len;
      this.options = options != null ? options : {};
      this.disposables = new CompositeDisposable();
      if (this.options.scopeName) {
        namespace = 'editor';
        scopedSettings = ['autoIndent', 'autoIndentOnPaste', 'invisibles', 'nonWordCharacters', 'normalizeIndentOnPaste', 'preferredLineLength', 'scrollPastEnd', 'showIndentGuide', 'showInvisibles', 'softWrap', 'softWrapAtPreferredLineLength', 'tabLength'];
        settings = {};
        for (_i = 0, _len = scopedSettings.length; _i < _len; _i++) {
          name = scopedSettings[_i];
          settings[name] = atom.config.get(name, {
            scope: [this.options.scopeName]
          });
        }
      } else {
        settings = atom.config.get(namespace);
      }
      this.appendSettings(namespace, settings);
      this.bindInputFields();
      this.bindSelectFields();
      return this.bindEditors();
    };

    SettingsPanel.prototype.detached = function() {
      return this.disposables.dispose();
    };

    SettingsPanel.prototype.appendSettings = function(namespace, settings) {
      var icon, includeTitle, sortedSettings, title, _ref1, _ref2;
      if (_.isEmpty(settings)) {
        return;
      }
      title = this.options.title;
      includeTitle = (_ref1 = this.options.includeTitle) != null ? _ref1 : true;
      if (includeTitle) {
        if (title == null) {
          title = "" + (_.undasherize(_.uncamelcase(namespace))) + " Settings";
        }
      } else {
        if (title == null) {
          title = "Settings";
        }
      }
      icon = (_ref2 = this.options.icon) != null ? _ref2 : 'gear';
      sortedSettings = this.sortSettings(namespace, settings);
      return this.append($$(function() {
        return this.div({
          "class": 'section-container'
        }, (function(_this) {
          return function() {
            _this.div({
              "class": "block section-heading icon icon-" + icon
            }, title);
            return _this.div({
              "class": 'section-body'
            }, function() {
              var name, _i, _len, _results;
              _results = [];
              for (_i = 0, _len = sortedSettings.length; _i < _len; _i++) {
                name = sortedSettings[_i];
                _results.push(appendSetting.call(_this, namespace, name, settings[name]));
              }
              return _results;
            });
          };
        })(this));
      }));
    };

    SettingsPanel.prototype.sortSettings = function(namespace, settings) {
      return _.chain(settings).keys().sortBy(function(name) {
        return name;
      }).sortBy(function(name) {
        var _ref1;
        return (_ref1 = atom.config.getSchema("" + namespace + "." + name)) != null ? _ref1.order : void 0;
      }).value();
    };

    SettingsPanel.prototype.bindInputFields = function() {
      return this.find('input[id]').toArray().forEach((function(_this) {
        return function(input) {
          var name, type;
          input = $(input);
          name = input.attr('id');
          type = input.attr('type');
          _this.observe(name, function(value) {
            if (type === 'checkbox') {
              return input.prop('checked', value);
            } else {
              if ((value != null) && type === 'color') {
                value = value.toHexString();
              }
              if (value) {
                return input.val(value);
              }
            }
          });
          return input.on('change', function() {
            var setNewValue, value;
            value = input.val();
            if (type === 'checkbox') {
              value = !!input.prop('checked');
            } else {
              value = _this.parseValue(type, value);
            }
            setNewValue = function() {
              return _this.set(name, value);
            };
            if (type === 'color') {
              clearTimeout(_this.colorDebounceTimeout);
              return _this.colorDebounceTimeout = setTimeout(setNewValue, 100);
            } else {
              return setNewValue();
            }
          });
        };
      })(this));
    };

    SettingsPanel.prototype.observe = function(name, callback) {
      var params;
      params = {
        sources: [atom.config.getUserConfigPath()]
      };
      if (this.options.scopeName != null) {
        params.scope = [this.options.scopeName];
      }
      return this.disposables.add(atom.config.observe(name, params, callback));
    };

    SettingsPanel.prototype.isDefault = function(name) {
      var params;
      params = {
        sources: [atom.config.getUserConfigPath()]
      };
      if (this.options.scopeName != null) {
        params.scope = [this.options.scopeName];
      }
      return atom.config.get(name, params) == null;
    };

    SettingsPanel.prototype.getDefault = function(name) {
      var params;
      params = {
        excludeSources: [atom.config.getUserConfigPath()]
      };
      if (this.options.scopeName != null) {
        params.scope = [this.options.scopeName];
      }
      return atom.config.get(name, params);
    };

    SettingsPanel.prototype.set = function(name, value) {
      if (this.options.scopeName) {
        if (value === void 0) {
          return atom.config.unset(name, {
            scopeSelector: this.options.scopeName
          });
        } else {
          return atom.config.set(name, value, {
            scopeSelector: this.options.scopeName
          });
        }
      } else {
        return atom.config.set(name, value);
      }
    };

    SettingsPanel.prototype.bindSelectFields = function() {
      return this.find('select[id]').toArray().forEach((function(_this) {
        return function(select) {
          var name;
          select = $(select);
          name = select.attr('id');
          _this.observe(name, function(value) {
            return select.val(value);
          });
          return select.change(function() {
            return _this.set(name, select.val());
          });
        };
      })(this));
    };

    SettingsPanel.prototype.bindEditors = function() {
      return this.find('atom-text-editor[id]').views().forEach((function(_this) {
        return function(editorView) {
          var defaultValue, editor, name, type;
          editor = editorView.getModel();
          name = editorView.attr('id');
          type = editorView.attr('type');
          if (defaultValue = _this.valueToString(_this.getDefault(name))) {
            editor.setPlaceholderText("Default: " + defaultValue);
          }
          _this.observe(name, function(value) {
            var stringValue, _ref1;
            if (_this.isDefault(name)) {
              stringValue = '';
            } else {
              stringValue = (_ref1 = _this.valueToString(value)) != null ? _ref1 : '';
            }
            if (stringValue === editor.getText()) {
              return;
            }
            if (_.isEqual(value, _this.parseValue(type, editor.getText()))) {
              return;
            }
            return editorView.setText(stringValue);
          });
          return editor.onDidStopChanging(function() {
            return _this.set(name, _this.parseValue(type, editor.getText()));
          });
        };
      })(this));
    };

    SettingsPanel.prototype.valueToString = function(value) {
      if (_.isArray(value)) {
        return value.join(', ');
      } else {
        return value != null ? value.toString() : void 0;
      }
    };

    SettingsPanel.prototype.parseValue = function(type, value) {
      var arrayValue, floatValue, val;
      if (value === '') {
        value = void 0;
      } else if (type === 'number') {
        floatValue = parseFloat(value);
        if (!isNaN(floatValue)) {
          value = floatValue;
        }
      } else if (type === 'array') {
        arrayValue = (value || '').split(',');
        value = (function() {
          var _i, _len, _results;
          _results = [];
          for (_i = 0, _len = arrayValue.length; _i < _len; _i++) {
            val = arrayValue[_i];
            if (val) {
              _results.push(val.trim());
            }
          }
          return _results;
        })();
      }
      return value;
    };

    return SettingsPanel;

  })(View);


  /*
   * Space Pen Helpers
   */

  isEditableArray = function(array) {
    var item, _i, _len;
    for (_i = 0, _len = array.length; _i < _len; _i++) {
      item = array[_i];
      if (!_.isString(item)) {
        return false;
      }
    }
    return true;
  };

  appendSetting = function(namespace, name, value) {
    if (namespace === 'core') {
      if (name === 'themes') {
        return;
      }
      if (name === 'disabledPackages') {
        return;
      }
    }
    return this.div({
      "class": 'control-group'
    }, (function(_this) {
      return function() {
        return _this.div({
          "class": 'controls'
        }, function() {
          var schema;
          schema = atom.config.getSchema("" + namespace + "." + name);
          if (schema != null ? schema["enum"] : void 0) {
            return appendOptions.call(_this, namespace, name, value);
          } else if ((schema != null ? schema.type : void 0) === 'color') {
            return appendColor.call(_this, namespace, name, value);
          } else if (_.isBoolean(value) || (schema != null ? schema.type : void 0) === 'boolean') {
            return appendCheckbox.call(_this, namespace, name, value);
          } else if (_.isArray(value) || (schema != null ? schema.type : void 0) === 'array') {
            if (isEditableArray(value)) {
              return appendArray.call(_this, namespace, name, value);
            }
          } else if (_.isObject(value) || (schema != null ? schema.type : void 0) === 'object') {
            return appendObject.call(_this, namespace, name, value);
          } else {
            return appendEditor.call(_this, namespace, name, value);
          }
        });
      };
    })(this));
  };

  getSettingTitle = function(keyPath, name) {
    var title, _ref1;
    if (name == null) {
      name = '';
    }
    title = (_ref1 = atom.config.getSchema(keyPath)) != null ? _ref1.title : void 0;
    return title || _.uncamelcase(name).split('.').map(_.capitalize).join(' ');
  };

  getSettingDescription = function(keyPath) {
    var _ref1;
    return ((_ref1 = atom.config.getSchema(keyPath)) != null ? _ref1.description : void 0) || '';
  };

  appendOptions = function(namespace, name, value) {
    var description, keyPath, options, title, _ref1, _ref2;
    keyPath = "" + namespace + "." + name;
    title = getSettingTitle(keyPath, name);
    description = getSettingDescription(keyPath);
    options = (_ref1 = (_ref2 = atom.config.getSchema(keyPath)) != null ? _ref2["enum"] : void 0) != null ? _ref1 : [];
    this.label({
      "class": 'control-label'
    }, (function(_this) {
      return function() {
        _this.div({
          "class": 'setting-title'
        }, title);
        return _this.div({
          "class": 'setting-description'
        }, description);
      };
    })(this));
    return this.select({
      id: keyPath,
      "class": 'form-control'
    }, (function(_this) {
      return function() {
        var option, _i, _len, _results;
        _results = [];
        for (_i = 0, _len = options.length; _i < _len; _i++) {
          option = options[_i];
          _results.push(_this.option({
            value: option
          }, option));
        }
        return _results;
      };
    })(this));
  };

  appendCheckbox = function(namespace, name, value) {
    var description, keyPath, title;
    keyPath = "" + namespace + "." + name;
    title = getSettingTitle(keyPath, name);
    description = getSettingDescription(keyPath);
    return this.div({
      "class": 'checkbox'
    }, (function(_this) {
      return function() {
        _this.label({
          "for": keyPath
        }, function() {
          _this.input({
            id: keyPath,
            type: 'checkbox'
          });
          return _this.div({
            "class": 'setting-title'
          }, title);
        });
        return _this.div({
          "class": 'setting-description'
        }, description);
      };
    })(this));
  };

  appendColor = function(namespace, name, value) {
    var description, keyPath, title;
    keyPath = "" + namespace + "." + name;
    title = getSettingTitle(keyPath, name);
    description = getSettingDescription(keyPath);
    return this.div({
      "class": 'color'
    }, (function(_this) {
      return function() {
        _this.label({
          "for": keyPath
        }, function() {
          _this.input({
            id: keyPath,
            type: 'color'
          });
          return _this.div({
            "class": 'setting-title'
          }, title);
        });
        return _this.div({
          "class": 'setting-description'
        }, description);
      };
    })(this));
  };

  appendEditor = function(namespace, name, value) {
    var description, keyPath, title, type;
    keyPath = "" + namespace + "." + name;
    if (_.isNumber(value)) {
      type = 'number';
    } else {
      type = 'string';
    }
    title = getSettingTitle(keyPath, name);
    description = getSettingDescription(keyPath);
    this.label({
      "class": 'control-label'
    }, (function(_this) {
      return function() {
        _this.div({
          "class": 'setting-title'
        }, title);
        return _this.div({
          "class": 'setting-description'
        }, description);
      };
    })(this));
    return this.div({
      "class": 'controls'
    }, (function(_this) {
      return function() {
        return _this.div({
          "class": 'editor-container'
        }, function() {
          return _this.subview(keyPath.replace(/\./g, ''), new TextEditorView({
            mini: true,
            attributes: {
              id: keyPath,
              type: type
            }
          }));
        });
      };
    })(this));
  };

  appendArray = function(namespace, name, value) {
    var description, keyPath, title;
    keyPath = "" + namespace + "." + name;
    title = getSettingTitle(keyPath, name);
    description = getSettingDescription(keyPath);
    this.label({
      "class": 'control-label'
    }, (function(_this) {
      return function() {
        _this.div({
          "class": 'setting-title'
        }, title);
        return _this.div({
          "class": 'setting-description'
        }, description);
      };
    })(this));
    return this.div({
      "class": 'controls'
    }, (function(_this) {
      return function() {
        return _this.div({
          "class": 'editor-container'
        }, function() {
          return _this.subview(keyPath.replace(/\./g, ''), new TextEditorView({
            mini: true,
            attributes: {
              id: keyPath,
              type: 'array'
            }
          }));
        });
      };
    })(this));
  };

  appendObject = function(namespace, name, value) {
    var key, _i, _len, _ref1, _results;
    _ref1 = _.keys(value).sort();
    _results = [];
    for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
      key = _ref1[_i];
      _results.push(appendSetting.call(this, namespace, "" + name + "." + key, value[key]));
    }
    return _results;
  };

}).call(this);
