+function ($) { "use strict";

  /**
   * The zoom service
   */
  function ZoomService () {
    this._activeZoom            =
    this._initialScrollPosition =
    this._initialTouchPosition  =
    this._touchMoveListener     = null

    this._$document = $(document)
    this._$window   = $(window)
    this._$body     = $(document.body)
  }

  ZoomService.prototype.listen = function () {
    this._$body.on('click', '[data-action="zoom"]', $.proxy(this._zoom, this))
  }

  ZoomService.prototype._zoom = function (e) {
    if($('.zoom-overlay').length) {
      return
    }
    //e.target.classList.remove("img_cover");

    var target = e.target
    if (!target || target.tagName != 'IMG') return

    if (e.metaKey) return window.open(e.target.src, '_blank')

    if (target.width >= (window.innerWidth - Zoom.OFFSET)) return

    this._activeZoomClose(true)

    this._activeZoom = new Zoom(target)
    this._activeZoom.zoomImage()
    this.currentTarget = target;
    target.style.opacity = '1';
    this.currentIndex  = parseInt(target.getAttribute('data-index'));
    this.currentTarget.setAttribute('data-ori', this.currentTarget.src);

    // todo(fat): probably worth throttling this
    this._$window.on('scroll.zoom', $.proxy(this._scrollHandler, this))

    this._$document.on('click.zoom', $.proxy(this._clickHandler, this))
    this._$document.on('keyup.zoom', $.proxy(this._keyHandler, this))
    this._$document.on('touchstart.zoom', $.proxy(this._touchStart, this))

    e.stopPropagation()
  }

  ZoomService.prototype._activeZoomClose = function (forceDispose) {
    if (!this._activeZoom) return

    if (forceDispose) {
      this._activeZoom.dispose()
    } else {
      this._activeZoom.close()
    }

    this._$window.off('.zoom')
    this._$document.off('.zoom')

    this._activeZoom = null
    if(this.currentTarget && this.currentTarget.className.indexOf('image-item') >= 0) {
      this.currentTarget.style.opacity = '0';
    }
    this.currentTarget.src = this.currentTarget.getAttribute('data-ori');
  }

  ZoomService.prototype._scrollHandler = function (e) {
    if (this._initialScrollPosition === null) this._initialScrollPosition = window.scrollY
    var deltaY = this._initialScrollPosition - window.scrollY
    if (Math.abs(deltaY) >= 40) this._activeZoomClose()
  }

  ZoomService.prototype._keyHandler = function (e) {
    var self = this;
    if (e.keyCode == 27) this._activeZoomClose()
    else if(e.keyCode === 37) {
      if(this.currentIndex > 0) {
        
        this.currentTarget.src = wechatImages[--this.currentIndex];
        var img = document.createElement('img')
        img.onload = $.proxy(function () {
          self._activeZoom._fullHeight = Number(img.height);
          self._activeZoom._fullWidth = Number(img.width);
          self._activeZoom._calculateZoom();
          self._activeZoom._triggerAnimation(self._activeZoom.offset)
        }, this)
        img.src = this.currentTarget.src
      }
    }
    else if(e.keyCode === 39) {
      if(this.currentIndex < wechatImages.length - 1) {
        this.currentTarget.src = wechatImages[++this.currentIndex];
        var img = document.createElement('img')
        img.onload = $.proxy(function () {
          self._activeZoom._fullHeight = Number(img.height);
          self._activeZoom._fullWidth = Number(img.width);
          self._activeZoom._calculateZoom();
          self._activeZoom._triggerAnimation(self._activeZoom.offset)
        }, this)
        img.src = this.currentTarget.src 
      }
    }
  }

  ZoomService.prototype._clickHandler = function (e) {
    e.stopPropagation()
    e.preventDefault()
    this._activeZoomClose()
  }

  ZoomService.prototype._touchStart = function (e) {
    this._initialTouchPosition = e.touches[0].pageY
    $(e.target).on('touchmove.zoom', $.proxy(this._touchMove, this))
  }

  ZoomService.prototype._touchMove = function (e) {
    if (Math.abs(e.touches[0].pageY - this._initialTouchPosition) > 10) {
      this._activeZoomClose()
      $(e.target).off('touchmove.zoom')
    }
  }


  /**
   * The zoom object
   */
  function Zoom (img) {
    this._fullHeight      =
    this._fullWidth       =
    this._overlay         =
    this._targetImageWrap = null

    this._targetImage = img

    this._$body = $(document.body)
  }

  Zoom.OFFSET = 80
  Zoom._MAX_WIDTH = 2560
  Zoom._MAX_HEIGHT = 4096

  Zoom.prototype.zoomImage = function () {
    var img = document.createElement('img')
    img.onload = $.proxy(function () {
      this._fullHeight = Number(img.height)
      this._fullWidth = Number(img.width)
      this._zoomOriginal()
    }, this)
    img.src = this._targetImage.src
  }

  Zoom.prototype._zoomOriginal = function () {
    this._targetImageWrap           = document.createElement('div')
    this._targetImageWrap.className = 'zoom-img-wrap'
    if(!$('.zoom-img-wrap').length) {
      this._targetImage.parentNode.insertBefore(this._targetImageWrap, this._targetImage)
      this._targetImageWrap.appendChild(this._targetImage)
    }

    $(this._targetImage)
      .addClass('zoom-img')
      .addClass('img_contain')
      .removeClass('img_cover')
      .attr('data-action', 'zoom-out')

    this._overlay           = document.createElement('div')
    this._overlay.className = 'zoom-overlay'
    //$('.current-tab')[0].appendChild(this._overlay)
    if(!$('.zoom-overlay').length) {
      document.body.appendChild(this._overlay);
    }

    this._calculateZoom()
    this._triggerAnimation()
  }

  Zoom.prototype._calculateZoom = function () {
    this._targetImage.offsetWidth // repaint before animating

    var originalFullImageWidth  = this._fullWidth
    var originalFullImageHeight = this._fullHeight

    var scrollTop = window.scrollY

    var maxScaleFactor = originalFullImageWidth / this._targetImage.width

    var viewportHeight = (window.innerHeight - Zoom.OFFSET)
    var viewportWidth  = (window.innerWidth - Zoom.OFFSET)
    //console.log(this._fullWidth, this._fullHeight)
    var imageAspectRatio    = originalFullImageWidth / originalFullImageHeight
    var viewportAspectRatio = viewportWidth / viewportHeight

    if (originalFullImageWidth < viewportWidth && originalFullImageHeight < viewportHeight) {
      this._imgScaleFactor = maxScaleFactor

    } else if (imageAspectRatio < viewportAspectRatio) {
      this._imgScaleFactor = (viewportHeight / originalFullImageHeight) * maxScaleFactor

    } else {
      this._imgScaleFactor = (viewportWidth / originalFullImageWidth) * maxScaleFactor
    }
  }

  Zoom.prototype._triggerAnimation = function (imageOffset) {
    this._targetImage.offsetWidth // repaint before animating
    //console.log(this._targetImage.offsetWidth)
    var imageOffset = imageOffset || $(this._targetImage).offset()
    this.offset = imageOffset;
    var scrollTop   = window.scrollY
    var viewportY = scrollTop + (window.innerHeight / 2)
    var viewportX = (window.innerWidth / 2)

    var imageCenterY = imageOffset.top + (this._targetImage.height / 2)
    var imageCenterX = imageOffset.left + (this._targetImage.width / 2)

    this._translateY = viewportY - imageCenterY
    this._translateX = viewportX - imageCenterX

    $(this._targetImage).css('transform', 'scale(' + this._imgScaleFactor + ')')
    $(this._targetImageWrap).css('transform', 'translate(' + this._translateX + 'px, ' + this._translateY + 'px) translateZ(0)')

    this._$body.addClass('zoom-overlay-open')
  }

  Zoom.prototype.close = function () {
    this._$body
      .removeClass('zoom-overlay-open')
      .addClass('zoom-overlay-transitioning')

    // we use setStyle here so that the correct vender prefix for transform is used
    $(this._targetImage).css('transform', '')
    $(this._targetImageWrap).css('transform', '')

    $(this._targetImage)
      .one($.support.transition.end, $.proxy(this.dispose, this))
      .emulateTransitionEnd(300)

    $(this._targetImage)
        .addClass('img_cover')
        .removeClass('img_contain')
  }

  Zoom.prototype.dispose = function () {
    if (this._targetImageWrap && this._targetImageWrap.parentNode) {
      $(this._targetImage)
        .removeClass('zoom-img')
        .attr('data-action', 'zoom')

      this._targetImageWrap.parentNode.replaceChild(this._targetImage, this._targetImageWrap)
      this._overlay.parentNode.removeChild(this._overlay)

      this._$body.removeClass('zoom-overlay-transitioning')
    }
  }

  new ZoomService().listen()

}(jQuery)
