path = require('path')
fs = require('fs')
app = window.app

zoomListImgCSS = (zoom) ->
    ret = "
                .file-list-view .file-box {
                    width: #{102 * zoom}px;
                    height: #{150 * zoom}px;
                 }

                .file-list-view .file-box .image-box {
                    width: #{100 * zoom}px;
                    height: #{100 * zoom}px;
                }
                .file-list-view .file-box .image-box .img {
                    line-height: #{100 * zoom}px;
                }
                .file-list-view .file-box .image-box .img img {
                    max-width: #{100 * zoom - 15}px;
                    max-height: #{100 * zoom - 15}px;
                }

                "
    return ret

imgBackgroundCSS = (color)->
    transBgPath = path.join(window.FOLDERS.IMG, 'bg-transparent.png')

    if not color or color == 'transparent'
        bg = "background-image: url(#{transBgPath})"
    else
        bg = "background-color: #{color}"

    ret = "
                    .file-list-view .file-box .image-box {
                        #{bg}
                    }
                "
    return ret

zoomDiffBoxCSS = (zoom) ->
    ret = "
        .canvas .diff-box {
            transform: scale(#{ zoom });
        }
    "
    return ret


app.controller 'FileViewController', ($scope, $rootScope, FileStatusService, Redirector, $timeout) ->
    $scope.needShow = -> Redirector.isCurrentView(Redirector.views.file)
    $scope.model =
        filesInfo: null

    $scope.MODE =
        LIST: 'list'
        DIFF: 'diff'

    $scope.drop = (files) ->
        console.log '[FileViewController drop] files', files
        s = FileStatusService
        for file in files
            s.load(file.path)

    init = ->
        $scope.listMode()
        $scope.isOriFront = false
        $scope.currentModel = null
        $scope.refreshStamp = Date.now()


    $scope.$watch (-> (i.progress for i in FileStatusService.model())), (()->
        m = FileStatusService.model()
        $scope.model.filesInfo = m
        return init() if m.length == 0
        $scope.selectedManager.singleSelect 0 if (i for i in m when i.selected).length == 0

        $timeout (-> $scope.refreshStamp = Date.now()), 50
        console.log '[FileViewController $watch] $scope.currentModel', $scope.currentModel
        console.log '[FileViewController $watch] $scope.model.filesInfo', $scope.model.filesInfo
    ), true


    # select
    $scope.selectedManager =
        allSelected: []
        _lastControlIndex: -1
        _lastShiftIndex: -1

        singleSelect: (index) ->
            sm = $scope.selectedManager
            $scope.model.filesInfo[index].selected = true
            sm._lastControlIndex = index
            sm.updateSelected()

        compressible: -> (i for i in $scope.selectedManager.allSelected when i.status.isCompressible())
        compressed: -> (i for i in $scope.selectedManager.allSelected when i.status.isCompressed())
        setSelected: (a, b, bool) ->
            return if a < 0 or b < 0
            m = $scope.model.filesInfo
            d = if a < b then m[a..b] else m[b..a]
            i.selected = bool for i in d

        onSelectAll: ->
            sm = $scope.selectedManager
            sm.setSelected 0, $scope.model.filesInfo.length, true
            sm.updateSelected()

        onDelete: ->
            sm = $scope.selectedManager
            FileStatusService.remove info for info in sm.allSelected

        onRestore: ->
            sm = $scope.selectedManager
            for info in sm.compressed()
                reader = info.restoreToOrigin()
                reader.on 'end', ->                     # 防止过早刷新而未写完file
                    $timeout (-> $scope.refreshStamp = Date.now()), 10

                console.log '[FileViewController selectedManager onRestore] 1', info.fullPath
            sm.updateSelected()

        onAutoCompress: ->
            sm = $scope.selectedManager
            info.setAutoCompress true for info in sm.compressible()
            sm.updateSelected()

        updateSelected: ->
            sm = $scope.selectedManager
            allSelected = (i for i in $scope.model.filesInfo when i.selected)
            $scope.currentModel = if allSelected.length == 1 then allSelected[0] else null

            sm.allSelected = allSelected
            console.log '[FileViewController updateSelected] sm', sm

        onModelSelect: (info, e) ->
            sm = $scope.selectedManager
            m = $scope.model.filesInfo
            curIndex = m.indexOf info
            setSelected = sm.setSelected

            if e.metaKey or e.ctrlKey
                info.selected = not info.selected
                sm._lastControlIndex = curIndex
                sm._lastShiftIndex = -1
            else if e.shiftKey
                setSelected curIndex, sm._lastShiftIndex, false
                setSelected curIndex, sm._lastControlIndex, true
                sm._lastShiftIndex = curIndex
            else
                setSelected 0, m.length - 1, false
                info.selected = true
                sm._lastControlIndex = curIndex
                sm._lastShiftIndex = -1
            sm.updateSelected()

    # -- select

    $scope.listMode = ->
        $scope.currentMode = $scope.MODE.LIST

    $scope.diffMode = ()->
        return if not $scope.currentModel
        $scope.originModel =
            fullPath: $scope.currentModel.backupFullPath
        #            fullPath: '/Users/zhangchenglong/Desktop/logo 3.png'
        $scope.currentMode = $scope.MODE.DIFF
#        $scope.zoom 1, $scope.zoomDiffBox
#        $timeout (->return $scope.zoomDiffBox.center()), 0
        $scope.zoomDiffBox.autoFit()
        $scope.animateZoomInfo()

    # compress progress
    $scope.maskHandler = (progress)->
        p = FileStatusService.PROGRESS
        ret = null
        switch progress
            when p.WAITING
                ret =
                    class: 'waiting'
                    text: '等待中'

            when p.COMPRESSING
                ret =
                    class: 'compressing'
                    text: '压缩中'

            when p.COMPRESS_ERROR
                ret =
                    class: 'error'
                    text: '出错'

            when p.LIMIT
                ret =
                    class: 'limit'
                    text: '压缩受限'

            when p.ERROR_FORMAT
                ret =
                    class: 'error'
                    text: '格式错误'
        return ret

    $scope.COMPRESS_PROGRESS = FileStatusService.PROGRESS
    # -- compress progress


    ## zoom
    $scope.zoom = (cur, zoomObject) ->
        floor = (x, digit) -> return Math.floor(x * Math.pow(10, digit)) / Math.pow(10, digit)
        zoomObject.cur = floor cur, 4
        zoomObject.curShow = floor cur * 100, 0
    ## -- zoom


    ## zoom list img // implement zoom interface
    $scope.zoomListImg =
        step: 0.5 # mul div
        min: 1
        max: 4
        cur: 1
        zoomOut: ->
            zoomObject = $scope.zoomListImg
            $scope.zoom Math.max(zoomObject.cur - zoomObject.step, zoomObject.min), zoomObject
        zoomIn: ->
            zoomObject = $scope.zoomListImg
            $scope.zoom Math.min(zoomObject.cur + zoomObject.step, zoomObject.max), zoomObject

        CSS: -> zoomListImgCSS $scope.zoomListImg.cur
    ## -- zoom list img


    ## zoom diffBox  // implement zoom interface
    $scope.zoomDiffBox =
        step: 0.5
        min: 0.25
        max: 4
        cur: 1
        curShow: 100
        center: false
        toNearestStep: (n)->
            obj = $scope.zoomDiffBox
            r = obj.step * Math.floor(n/obj.step + 0.49)
            r = Math.min(Math.max(r, obj.min), obj.max)
        zoomOut: ->
            zoomObject = $scope.zoomDiffBox
            $scope.zoom zoomObject.toNearestStep(zoomObject.cur - zoomObject.step), zoomObject
        zoomIn: ->
            zoomObject = $scope.zoomDiffBox
            $scope.zoom zoomObject.toNearestStep(zoomObject.cur + zoomObject.step), zoomObject

        CSS: -> zoomDiffBoxCSS $scope.zoomDiffBox.cur
        center: ->
            canvas = $scope.canvasElement
            diffBox = $scope.diffBoxElement
            img = $scope.diffImageElement
            left = canvas.clientWidth / 2 - img.width / 2
            top = canvas.clientHeight / 2 - img.height / 2
            diffBox.style.setProperty 'left', left + 'px', null
            diffBox.style.setProperty 'top', top + 'px', null

        _getRatio: ->
            canvas = $scope.canvasElement
            img = $scope.diffImageElement
            fitPadding = 10
            ratio = Math.min((canvas.clientWidth - fitPadding)/ img.width, (canvas.clientHeight - fitPadding)/ img.height)
            return ratio

        fitOrigin: ->
            self = $scope.zoomDiffBox
            $scope.zoom 1, self
            self.center()
            return

        fitFullScreen: ->
            self = $scope.zoomDiffBox
            ratio = self._getRatio()
            console.log '[FileViewController zoomDiffBox] fit ratio', ratio
            $scope.zoom ratio, self
            self.center()

        autoFit: -> # 占满超过自身,则原大小
            self = $scope.zoomDiffBox
            ratio = self._getRatio()
            if ratio < 1
                self.fitFullScreen()
            else
                self.fitOrigin()

        zoomInBox: ->
            img = $scope.diffImageElement
            diffBox = $scope.diffBoxElement
            return if not $scope.canvasElement
            cr = $scope.canvasElement.getBoundingClientRect()
            ir = img.getBoundingClientRect()
            offsetLeft = (ir.width - img.width) / 2
            offsetTop = (ir.height - img.height) / 2

            leftPix = 20
            limit =
                left: {min: leftPix - ir.width, max: cr.width - leftPix}
                top: {min: leftPix - ir.height, max: cr.height - leftPix}

            if ir.left > limit.left.max
                left = limit.left.max

            if ir.left < limit.left.min
                left = limit.left.min

            if ir.top > limit.top.max
                top = limit.top.max

            if ir.top < limit.top.min
                top = limit.top.min

            if left or top
                left = ir.left if not left
                top = ir.top if not top
                left += offsetLeft
                top += offsetTop
                diffBox.style.setProperty 'left', left + 'px', null
                diffBox.style.setProperty 'top', top + 'px', null

    $scope.$watch (-> $scope.zoomDiffBox.CSS()), ->
        $timeout $scope.zoomDiffBox.zoomInBox, 100

    $scope.$watch 'zoomDiffBox.curShow', ->
        obj = $scope.zoomDiffBox
        return if Math.floor(obj.cur * 100) == obj.curShow # 因为精度问题的调整, 不修改
        cur = obj.curShow / 100
        cur = Math.max(cur, obj.min)
        cur = Math.min(cur, obj.max)
        $scope.zoom cur, obj

    listenWheelZoom = ->
        return $timeout listenWheelZoom, 1000 if not $scope.canvasElement
        $scope.canvasElement.addEventListener 'mousewheel', (e)->
            return if $scope.currentMode != $scope.MODE.DIFF

            d = $scope.diffBoxElement
            dr = d.getBoundingClientRect()
            xOnDiff = Math.min(dr.width, Math.max(e.x - dr.left, 0))
            yOnDiff = Math.min(dr.height, Math.max(0, e.y - dr.top))

            anchorDistToCenter =
                x: dr.width/2 - xOnDiff
                y: dr.height/2 - yOnDiff
            lastScale = $scope.zoomDiffBox.cur

            if e.wheelDelta > 0
                $scope.zoomDiffBox.zoomIn()
            else
                $scope.zoomDiffBox.zoomOut()

            s = $scope.zoomDiffBox.cur / lastScale - 1
            left = d.offsetLeft + anchorDistToCenter.x * s
            top = d.offsetTop + anchorDistToCenter.y * s
            d.style.setProperty 'left', left + 'px', null
            d.style.setProperty 'top', top + 'px', null

            console.log "[FileView WheelZoom] scale:[#{lastScale}->#{$scope.zoomDiffBox.cur}], left:[#{d.offsetLeft}->#{left}]"

            $scope.$apply()
#            $timeout (->$scope.$apply()), 10

    listenWheelZoom()
    ## -- zoom diffBox

    ## diffBox animation
    $scope.showDiffZoomInfo = false
    animateZoomPromise = null
    $scope.animateZoomInfo = ->
        $scope.showDiffZoomInfo = false
        $timeout.cancel animateZoomPromise if animateZoomPromise
        $timeout (-> $scope.showDiffZoomInfo = true), 10
        animateZoomPromise = $timeout (-> $scope.showDiffZoomInfo = false), 2010

    $scope.$watch 'zoomDiffBox.cur', $scope.animateZoomInfo


    ## -- diffBox animation

    ## bg
    $scope.setBG = (color)->
        $scope.currentBG = color

    $scope.setBG 'dark'
    $scope.imgBackgroundCSS = imgBackgroundCSS
    ## -- bg


    ## key shortcut
    document.addEventListener 'keyup', (e) ->
#        console.log 'add event keyup', e.keyCode
        [ESC, DEL] = [27, 46]
        switch e.keyCode
            when ESC
                if $scope.currentMode = $scope.MODE.DIFF
                    $scope.listMode()
                    $scope.$apply()
            when DEL
                $scope.selectedManager.onDelete()
                $scope.$apply()

    Mousetrap.bind ['command+a', 'ctrl+a'], ->
        $scope.selectedManager.onSelectAll()
        $scope.$apply()
    ## -- key shortcut

    ## diff mouse move

    $scope.onMouseMove = (e) -> # cmp img
        return if not e
        rectBox = $scope.diffBoxElement.getBoundingClientRect()
        cur = $scope.zoomDiffBox.cur
#        console.log 'mousemove', e.x, rectBox.left
        x = Math.max(0, (e.x - rectBox.left) / cur)
        x = Math.min(rectBox.width / cur, x)
        document.querySelector('.ori-box').style.setProperty 'width', x.toFixed(0) + 'px', null
    ## -- diff mouse move

    $scope.reveal = (fullPath) ->
        return if not fullPath
        p = path.parse(fullPath)
        window.openExternal('file://' + p.dir)

    init()

    console.log '[FileViewController] init ok'
    return


