describe("SkinModel", function() {
  beforeEach(function() {
    this.server = sinon.fakeServer.create();
    this.server.autoRespond = true
  })

  afterEach(function() {
    this.server.restore();
    var Skin = window.require('core/models/skin')
    Skin.destroyAll({ajax: false})
    localStorage.clear()
  })

  it('should not update it\'s attributes when persisted to the server', function() {
    var Skin = window.require('core/models/skin')
    var skin = new Skin();

    this.server.respondWith([200, null, '{ "id": "42", "backgroundColor": "red" }']);

    skin.backgroundColor = 'blue';
    return skin.persist().then(function(promiseSkin) {
      skin.should.equal(promiseSkin);
      skin.id.should.equal('42');
      skin.backgroundColor.should.equal('blue');
    })
  });

  it('should not persist to localStorage in case of errors', function() {
    var Skin = window.require('core/models/skin')
    var skin = new Skin();

    this.server.respondWith([400, null,
      '{ "error": "Some error", "error_description": "Some error description" }']);

    var callback = sinon.spy();
    skin.on('change', callback)
    Skin.on('change', callback)

    return skin.persist().fail(function(error) {
      should.exist(error)
      Skin.all().should.be.empty
      callback.should.not.have.been.called
      should.not.exist(localStorage.Skin)
    })
  })

  it('should allow creating', function() {
    var Skin = window.require('core/models/skin')
    var skin = new Skin();

    this.server.respondWith('POST', '/api/v2/skins', [200, null, '{ "id": 42 }']);

    var createCallback = sinon.spy();
    skin.on('create', createCallback)
    Skin.on('create', createCallback)

    should.not.exist(skin.id);
    return skin.persist().then(function() {
      skin.id.should.equal(42);
      Skin.all().should.not.be.empty
      createCallback.should.have.been.calledTwice
    })
  });

  it('should handle create errors', function() {
    var Skin = window.require('core/models/skin')
    var skin = new Skin();

    this.server.respondWith('POST', '/api/v2/skins', [400, null,
      '{ "error": "Some error", "error_description": "Some error description" }']);

    var createCallback = sinon.spy();
    skin.on('create', createCallback)
    Skin.on('create', createCallback)

    should.not.exist(skin.id);
    return skin.persist().then(function() {
      throw new Error('Should not have saved')
    }, function(e) {
      e.should.exist
      e.message.should.equal('Some error description')
      Skin.all().should.be.empty
      createCallback.should.not.have.been.called
    })
  })

  it('should allow updating', function() {
    var Skin = window.require('core/models/skin')
    var skin = new Skin();

    this.server.respondWith('POST', '/api/v2/skins', [200, null, '{ "id": "42" }']);
    this.server.respondWith('POST', '/api/v2/skins/42', [200, null, '{ "id": "42" }']);

    var updateCallback = sinon.spy();

    should.not.exist(skin.id);
    return skin.persist()
      .then(function() {
        skin.on('update', updateCallback)
        Skin.on('update', updateCallback)
        return skin.persist()
      })
      .then(function() {
        skin.id.should.equal("42");
        Skin.all().should.not.be.empty
        updateCallback.should.have.been.calledTwice
      })
  });

  it('should handle update errors', function() {
    var Skin = window.require('core/models/skin')
    var skin = new Skin();

    this.server.respondWith('POST', '/api/v2/skins', [200, null, '{ "id": "42" }']);
    this.server.respondWith('POST', '/api/v2/skins/42', [400, null,
      '{ "error": "Some error", "error_description": "Some error description" }']);

    var updateCallback = sinon.spy();

    return skin.persist()
      .then(function() {
        skin.on('update', updateCallback)
        Skin.on('update', updateCallback)
        return skin.persist()
      }).then(function() {
        throw new Error('Should not have saved')
      }, function(e) {
        e.should.exist
        e.message.should.equal('Some error description')
        Skin.all().should.not.be.empty
        updateCallback.should.not.have.been.called
      })
  })

  it('should allow deleting', function(done) {
    var Skin = window.require('core/models/skin')
    var skin = new Skin();

    this.server.respondWith('POST', '/api/v2/skins', [200, null, '{ "id": "42" }']);
    this.server.respondWith('POST', '/api/v2/skins/42', [204, null, '']);

    var destroyCallback = sinon.spy();

    should.not.exist(skin.id);
    skin.persist()
      .then(function() {
        skin.on('destroy', destroyCallback)
        Skin.on('destroy', destroyCallback)
        skin.destroy({done: function() {
            Skin.all().should.be.empty
            destroyCallback.should.have.been.calledTwice
            done()
        }})
      })
  })

  it('should remove model even when delete fails', function(done) {
    // cristi: this is the actual behaviour of spine models
    var Skin = window.require('core/models/skin')
    var skin = new Skin();

    this.server.respondWith('POST', '/api/v2/skins', [200, null, '{ "id": "42" }']);
    this.server.respondWith('POST', '/api/v2/skins/42', [400, null,
      '{ "error": "Some error", "error_description": "Some error description" }']);

    var destroyCallback = sinon.spy();

    should.not.exist(skin.id);
    skin.persist()
      .then(function() {
        skin.on('destroy', destroyCallback)
        Skin.on('destroy', destroyCallback)
        skin.destroy({
          done: function() {
            done(new Error('Should not have deleted'))
          },
          fail: function(e) {
            e.should.exist
            e.message.should.equal('Some error description')
            Skin.all().should.be.empty
            destroyCallback.should.have.been.calledTwice
            done()
          }
        })
      })
  })

  it('should keep references intact after persisting', function() {
    var Skin = window.require('core/models/skin')
    var skin = new Skin({name: 'Some skin'});

    skin.save({ajax: false});

    var Composition = window.require('core/models/composition')
    var composition = new Composition()

    composition.skin_id = skin.id
    composition.save({ajax: false})
    composition.getSkin().name.should.equal('Some skin')

    this.server.respondWith([200, null, '{ "id": "42", "backgroundColor": "red" }']);

    return skin.persist().then(function(promiseSkin) {
      skin.id.should.equal('42');
      composition.getSkin().id.should.equal('42')
      composition.getSkin().name.should.equal('Some skin')
    })
  })
});
