'use strict';

var Model = require('ampersand-model');
var React = require('react');
var merge = require('lodash.merge');
var view = require('./view');
var constructModel = require('../util/ensureInstance').model;

module.exports = function(config) {
  if (config == null) {
    throw new Error('config parameter is required');
  }

  var ModelViewMixin = {
    displayName: 'modelView',
    propTypes: {
      model: React.PropTypes.oneOfType([
        React.PropTypes.func,
        React.PropTypes.object,
        React.PropTypes.instanceOf(Model)
      ]),
      data: React.PropTypes.object,
      routeIdAttribute: React.PropTypes.string
    },

    // most options can be passed via config or props
    // props takes precedence
    getDefaultProps: function(){
      return {
        model: config.model,
        data: config.data,
        routeIdAttribute: (config.routeIdAttribute || 'id')
      };
    },

    componentWillMount: function() {
      this._initialize();
    },

    componentWillReceiveProps: function(nextProps) {
      // if the next route id changed, redo the model
      // sometimes views get recycled
      var nextRouteIdAttribute = this.getParams()[nextProps.routeIdAttribute];
      if (nextRouteIdAttribute !== this.model.getId()) {
        this._initialize();
      }
    },

    modelFetchFailed: function(m, err) {
      if (config.modelFetchFailed) {
        return config.modelFetchFailed.apply(this, arguments);
      }
      throw new Error('Model fetch failed: ' + err);
    },

    _initialize: function() {
      // TODO: wtf
      var routeIdAttribute = this.getParams()[this.props.routeIdAttribute];
      var options = this.props;
      if (routeIdAttribute) {
        options = merge({
          id: routeIdAttribute
        }, options);
      }

      var model = constructModel(this.props.model, options);

      // no model specified in props or config
      if (!model) {
        throw new Error('modelView never got a model');
      }

      var setModel = (function(){
        this.model = model;
        this.listenTo(this.model, 'change', this.tryUpdate);
        if (this.modelDidFetch) {
          this.modelDidFetch();
        }
        this.tryUpdate();
      }).bind(this);

      if (model._needsInitialFetch) {
        model.fetch({
          success: setModel,
          error: this.modelFetchFailed
        });
      } else {
        setModel();
      }
    }
  };

  return view(config, [ModelViewMixin]);
};
@@ -635,16 +635,53 @@
 s.string
+,%0A      query: React.PropTypes.object
 %0A    %7D,%0A
@@ -1002,24 +1002,34 @@
 _initialize(
+this.props
 );%0A    %7D,%0A%0A 
@@ -1333,16 +1333,25 @@
 tialize(
+nextProps
 );%0A     
@@ -1589,32 +1589,37 @@
 alize: function(
+props
 ) %7B%0A      // TOD
@@ -1671,21 +1671,16 @@
 arams()%5B
-this.
 props.ro
@@ -1716,21 +1716,16 @@
 tions = 
-this.
 props;%0A 
@@ -1873,21 +1873,16 @@
 ctModel(
-this.
 props.mo

add query to modelview