describe 'up.modal', ->

  u = up.util
  
  describe 'Javascript functions', ->

    assumedScrollbarWidth = 15

    describe 'up.modal.follow', ->

      it "loads the given link's destination in a dialog window", (done) ->
        $link = affix('a[href="/path/to"][up-modal=".middle"]').text('link')
        promise = up.modal.follow($link)
        expect(@lastRequest().url).toMatch /\/path\/to$/
        @respondWith """
          <div class="before">new-before</div>
          <div class="middle">new-middle</div>
          <div class="after">new-after</div>
          """
        promise.then ->
          expect($('.up-modal')).toExist()
          expect($('.up-modal-dialog')).toExist()
          expect($('.up-modal-dialog .middle')).toExist()
          expect($('.up-modal-dialog .middle')).toHaveText('new-middle')
          expect($('.up-modal-dialog .before')).not.toExist()
          expect($('.up-modal-dialog .after')).not.toExist()
          done()

    describe 'up.modal.visit', ->

      it "brings its own scrollbar, padding the body on the right in order to prevent jumping", (done) ->
        promise = up.modal.visit('/foo', target: '.container')

        @respondWith('<div class="container">text</div>')

        promise.then ->

          $modal = $('.up-modal')
          $body = $('body')
          expect($modal).toExist()
          expect($modal.css('overflow-y')).toEqual('scroll')
          expect($body.css('overflow-y')).toEqual('hidden')
          expect(parseInt($body.css('padding-right'))).toBeAround(assumedScrollbarWidth, 10)

          up.modal.close().then ->
            expect($body.css('overflow-y')).toEqual('scroll')
            expect(parseInt($body.css('padding-right'))).toBe(0)

            done()

      it 'pushes right-anchored elements away from the edge of the screen in order to prevent jumping', (done) ->

        $anchoredElement = affix('div[up-anchored=right]').css
          position: 'absolute'
          top: '0'
          right: '30px'

        promise = up.modal.visit('/foo', target: '.container')

        @respondWith('<div class="container">text</div>')

        promise.then ->
          expect(parseInt($anchoredElement.css('right'))).toBeAround(30 + assumedScrollbarWidth, 10)

          up.modal.close().then ->
            expect(parseInt($anchoredElement.css('right'))).toBeAround(30 , 10)
            done()

      it 'does not explode if the modal was closed before the response was received', ->
        up.modal.visit('/foo', target: '.container')
        up.modal.close()
        respond = => @respondWith('<div class="container">text</div>')
        expect(respond).not.toThrowError()
        expect($('.up-error')).not.toExist()

    describe 'up.modal.coveredUrl', ->

      it 'returns the URL behind the modal overlay', (done) ->
        up.history.replace('/foo')
        expect(up.modal.coveredUrl()).toBeUndefined()
        up.modal.visit('/bar', target: '.container')
        @respondWith('<div class="container">text</div>')
        expect(up.modal.coveredUrl()).toEndWith('/foo')
        up.modal.close().then ->
          expect(up.modal.coveredUrl()).toBeUndefined()
          done()


    describe 'up.modal.close', ->

      it 'closes a currently open modal'

      it 'does nothing if no modal is open'

    describe 'up.modal.source', ->

      it 'should have tests'

  describe 'unobtrusive behavior', ->
    
    describe 'a[up-modal]', ->
      
      it 'opens the clicked link in a modal', ->
        followSpy = up.modal.knife.mock('follow')
        $link = affix('a[href="/path"][up-modal=".foo"]')
        up.hello($link)
        $link.click()
        expect(followSpy).toHaveBeenCalledWith($link)

    describe '[up-close]', ->

      describe 'when clicked inside a modal', ->
      
        it 'closes the open modal and prevents the default action', ->
          $modal = affix('.up-modal')
          $link = $modal.affix('a[up-close]') # link is within the modal
          up.hello($link)
          wasDefaultPrevented = false
          wasClosed = false
          up.on 'click', 'a[up-close]', (event) ->
            wasDefaultPrevented = event.isDefaultPrevented()
            true # the line above might return false and cancel propagation / prevent default
          up.on 'up:modal:close', ->
            wasClosed = true
          $link.click()
          expect(wasClosed).toBe(true)
          expect(wasDefaultPrevented).toBe(true)

      describe 'when no modal is open', ->

        it 'does neither close the modal nor prevent the default action', ->
          $link = affix('a[up-close]') # link is outside the modal
          up.hello($link)
          wasDefaultPrevented = false
          wasClosed = false
          up.on 'click', 'a[up-close]', (event) ->
            wasDefaultPrevented = event.isDefaultPrevented()
            true # the line above might return false and cancel propagation / prevent default
          up.on 'up:modal:close', ->
            wasClosed = true
          $link.click()
          expect(wasClosed).toBe(false)
          expect(wasDefaultPrevented).toBe(false)

    describe 'when replacing content', ->

      beforeEach ->
        up.motion.config.enabled = false

      it 'prefers to replace a selector within the modal', ->
        $outside = affix('.foo').text('old outside')
        up.modal.visit('/path', target: '.foo')
        @respondWith("<div class='foo'>old inside</div>")
        up.flow.implant('.foo', "<div class='foo'>new text</div>")
        expect($outside).toBeInDOM()
        expect($outside).toHaveText('old outside')
        expect($('.up-modal-content')).toHaveText('new text')

      it 'auto-closes the modal when a replacement from inside the modal affects a selector behind the modal', ->
        affix('.outside').text('old outside')
        up.modal.visit('/path', target: '.inside')
        @respondWith("<div class='inside'>old inside</div>")
        up.flow.implant('.outside', "<div class='outside'>new outside</div>", origin: $('.inside'))
        expect($('.outside')).toHaveText('new outside')
        expect($('.up-modal')).not.toExist()

      it 'does not auto-close the modal when a replacement from inside the modal affects a selector inside the modal', ->
        affix('.outside').text('old outside')
        up.modal.visit('/path', target: '.inside')
        @respondWith("<div class='inside'>old inside</div>")
        up.flow.implant('.inside', "<div class='inside'>new inside</div>", origin: $('.inside'))
        expect($('.inside')).toHaveText('new inside')
        expect($('.up-modal')).toExist()

      it 'does not auto-close the modal when a replacement from outside the modal affects a selector outside the modal', ->
        affix('.outside').text('old outside')
        up.modal.visit('/path', target: '.inside')
        @respondWith("<div class='inside'>old inside</div>")
        up.flow.implant('.outside', "<div class='outside'>new outside</div>", origin: $('.outside'))
        expect($('.outside')).toHaveText('new outside')
        expect($('.up-modal')).toExist()

      it 'does not auto-close the modal when a replacement from outside the modal affects a selector inside the modal', ->
        affix('.outside').text('old outside')
        up.modal.visit('/path', target: '.inside')
        @respondWith("<div class='inside'>old inside</div>")
        up.flow.implant('.inside', "<div class='inside'>new inside</div>", origin: $('.outside'))
        expect($('.inside')).toHaveText('new inside')
        expect($('.up-modal')).toExist()

      it 'does not auto-close the modal when the new fragment is within a popup', ->
        up.modal.visit('/modal', target: '.modal-content')
        @respondWith("<div class='modal-content'></div>")
        up.popup.attach('.modal-content', url: '/popup', target: '.popup-content')
        @respondWith("<div class='popup-content'></div>")
        expect($('.up-modal')).toExist()
        expect($('.up-popup')).toExist()

    describe 'when following links inside a modal', ->

      it 'prefers to replace a selector within the modal', ->

      it 'auto-closes the modal if a selector behind the modal gets replaced'

      it "doesn't auto-close the modal if a selector behind the modal if the modal is sticky"

      it "doesn't auto-close the modal if the new fragment is a popup"