/*
* jQuery.eraser v0.5.2
* makes any image or canvas erasable by the user, using touch or mouse input
* https://github.com/boblemarin/jQuery.eraser
*
* Usage:
*
* $('#myImage').eraser(); // simple way
*
* $('#canvas').eraser( {
*   size: 20, // define brush size (default value is 40)
*   completeRatio: .65, // allows to call function when a erased ratio is reached (between 0 and 1, default is .7 )
*   completeFunction: myFunction // callback function when complete ratio is reached
* } );
*
* $('#image').eraser( 'clear' ); // erases all canvas content
*
* $('#image').eraser( 'reset' ); // revert back to original content
*
* $('#image').eraser( 'size', 80 ); // change the eraser size
*
* $('#image').eraser( 'enable/disable' ); // enable or disable erasing
*
* $('#image').eraser( 'enabled' ); // returns whether the eraser is enabled
*
*
* https://github.com/boblemarin/jQuery.eraser
* http://minimal.be/lab/jQuery.eraser/
*
* Copyright (c) 2010 boblemarin emeric@minimal.be http://www.minimal.be
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

(function($) {
    var methods = {

        init: function(options) {
            return this.each(function() {
                var $this = $(this),
                data = $this.data('eraser');

                if (!data) {

                    var handleImage = function() {
                        var $canvas = $('<canvas/>'),
                        canvas = $canvas.get(0),
                        ctx = canvas.getContext('2d'),

                        // calculate scale ratio for high DPI devices
                        // http://www.html5rocks.com/en/tutorials/canvas/hidpi/
                        devicePixelRatio = window.devicePixelRatio || 1,
                        backingStoreRatio = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1,
                        scaleRatio = devicePixelRatio / backingStoreRatio,

                        realWidth = $this.width(),
                        realHeight = $this.height(),
                        width = realWidth * scaleRatio,
                        height = realHeight * scaleRatio,
                        pos = $this.offset(),
                        enabled = (options && options.enabled === false) ? false: true,
                        size = ((options && options.size) ? options.size: 40) * scaleRatio,
                        completeRatio = (options && options.completeRatio) ? options.completeRatio: .7,
                        completeFunction = (options && options.completeFunction) ? options.completeFunction: null,
                        progressFunction = (options && options.progressFunction) ? options.progressFunction: null,
                        zIndex = $this.css('z-index') == "auto" ? 1 : $this.css('z-index'),
                        parts = [],
                        colParts = Math.floor(width / size),
                        numParts = colParts * Math.floor(height / size),
                        n = numParts,
                        that = $this[0],
                        firstClick = (options && options.firstClick) ? options.firstClick: null;

                        // replace target with canvas
                        $this.after($canvas);
                        canvas.id = that.id;
                        canvas.className = that.className;
                        canvas.width = width;
                        canvas.height = height;
                        canvas.style.width = realWidth.toString() + "px";
                        canvas.style.height = realHeight.toString() + "px";
                        ctx.drawImage(that, 0, 0, width, height);
                        $this.remove();

                        // prepare context for drawing operations
                        ctx.globalCompositeOperation = 'destination-out';
                        ctx.strokeStyle = 'rgba(255,0,0,255)';
                        ctx.lineWidth = size;

                        ctx.lineCap = 'round';
                        // bind events，只有在手机中才会有这个事件
                        $canvas.bind('mousedown.eraser', methods.mouseDown);
                        $canvas.bind('touchstart.eraser', methods.touchStart);
                        $canvas.bind('touchmove.eraser', methods.touchMove);
                        $canvas.bind('touchend.eraser', methods.touchEnd);

                        // reset parts
                        while (n--) parts.push(1);

                        // store values
                        data = {
                            posX: pos.left,
                            posY: pos.top,
                            touchDown: false,
                            touchID: -999,
                            touchX: 0,
                            touchY: 0,
                            ptouchX: 0,
                            ptouchY: 0,
                            canvas: $canvas,
                            ctx: ctx,
                            w: width,
                            h: height,
                            scaleRatio: scaleRatio,
                            source: that,
                            size: size,
                            parts: parts,
                            colParts: colParts,
                            numParts: numParts,
                            ratio: 0,
                            enabled: enabled,
                            complete: false,
                            completeRatio: completeRatio,
                            completeFunction: completeFunction,
                            progressFunction: progressFunction,
                            zIndex: zIndex,
                            firstClick : firstClick,
                            isRequest : false	//是否第一次请求
                        };
                        $canvas.data('eraser', data);

                        // listen for resize event to update offset values
                        $(window).resize(function() {
                            var pos = $canvas.offset();
                            data.posX = pos.left;
                            data.posY = pos.top;
                        });
                    }

                    if (this.complete && this.naturalWidth > 0) {
                        handleImage();
                    } else {
                        //this.onload = handleImage;
                        $this.on('load', handleImage);
                    }
                }
            });
        },

        touchStart: function(event) {
            var $this = $(this),
            data = $this.data('eraser');
            if (!data.touchDown) {
                var t = event.originalEvent.changedTouches[0],
                tx = t.pageX - data.posX,
                ty = t.pageY - data.posY;
                tx *= data.scaleRatio;
                ty *= data.scaleRatio;

                if (data.enabled) {
                	if(!data.isRequest){
						if(typeof data.firstClick == 'function') data.firstClick();
						data.isRequest = true;
						$this.data('eraser',data);
					}
                    methods.evaluatePoint(data, tx, ty);
                }else{
					toast("可用积分不足");
                }

                data.touchDown = true;
                data.touchID = t.identifier;
                data.touchX = tx;
                data.touchY = ty;
                event.preventDefault();
            }
        },

        touchMove: function(event) {
            var $this = $(this),
            data = $this.data('eraser');

            if (data.touchDown) {
                var ta = event.originalEvent.changedTouches,
                n = ta.length;
                while (n--) {
                    if (ta[n].identifier == data.touchID) {
                        var tx = ta[n].pageX - data.posX,
                        ty = ta[n].pageY - data.posY;
                        tx *= data.scaleRatio;
                        ty *= data.scaleRatio;

                        if (data.enabled) {
                            methods.evaluatePoint(data, tx, ty);
                            data.ctx.beginPath();
                            data.ctx.moveTo(data.touchX, data.touchY);
                            data.ctx.lineTo(tx, ty);
                            data.ctx.stroke();
                            $this.css({
                                "z-index": $this.css('z-index') == data.zIndex ? parseInt(data.zIndex) + 1 : data.zIndex
                            });
                        }

                        data.touchX = tx;
                        data.touchY = ty;

                        event.preventDefault();
                        break;
                    }
                }
            }
        },

        touchEnd: function(event) {
            var $this = $(this),
            data = $this.data('eraser');

            if (data.touchDown) {
                var ta = event.originalEvent.changedTouches,
                n = ta.length;
                while (n--) {
                    if (ta[n].identifier == data.touchID) {
                        data.touchDown = false;
                        event.preventDefault();
                        break;
                    }
                }
            }
        },

        evaluatePoint: function(data, tx, ty) {
            if (!data.enabled) return;
            var p = Math.floor(tx / data.size) + Math.floor(ty / data.size) * data.colParts;

            if (p >= 0 && p < data.numParts) {
                data.ratio += data.parts[p];
                data.parts[p] = 0;
                if (!data.complete) {
                    p = data.ratio / data.numParts;
                    if (p >= data.completeRatio) {
                        data.complete = true;
                        if (data.completeFunction != null) data.completeFunction();
                    } else {
                        if (data.progressFunction != null) data.progressFunction(p);
                    }
                }
            }

        },

        mouseDown: function(event) {
            var $this = $(this),
            data = $this.data('eraser'),
            tx = event.pageX - data.posX,
            ty = event.pageY - data.posY;
            tx *= data.scaleRatio;
            ty *= data.scaleRatio;

            data.touchDown = true;
            data.touchX = tx;
            data.touchY = ty;

            if (data.enabled) {
                methods.evaluatePoint(data, tx, ty);

                data.ctx.beginPath();
                data.ctx.moveTo(data.touchX - 1, data.touchY);
                data.ctx.lineTo(data.touchX, data.touchY);
                data.ctx.stroke();
            }

            $this.bind('mousemove.eraser', methods.mouseMove);
            $(document).bind('mouseup.eraser', data, methods.mouseUp);
            event.preventDefault();
        },

        mouseMove: function(event) {
            var $this = $(this),
            data = $this.data('eraser'),
            tx = event.pageX - data.posX,
            ty = event.pageY - data.posY;
            tx *= data.scaleRatio;
            ty *= data.scaleRatio;

            if (data.enabled) {
                methods.evaluatePoint(data, tx, ty);
                data.ctx.beginPath();
                data.ctx.moveTo(data.touchX, data.touchY);
                data.ctx.lineTo(tx, ty);
                data.ctx.stroke();
                $this.css({
                    "z-index": $this.css('z-index') == data.zIndex ? parseInt(data.zIndex) + 1 : data.zIndex
                });
            }

            data.touchX = tx;
            data.touchY = ty;

            event.preventDefault();
        },

        mouseUp: function(event) {
            var data = event.data,
            $this = data.canvas;

            data.touchDown = false;
            $this.unbind('mousemove.eraser');
            $(document).unbind('mouseup.eraser');
            event.preventDefault();
        },

        clear: function() {
            var $this = $(this),
            data = $this.data('eraser');
            if (data) {
                data.ctx.clearRect(0, 0, data.w, data.h);
                var n = data.numParts;
                while (n--) data.parts[n] = 0;
                data.ratio = data.numParts;
                data.complete = true;
//                if (data.completeFunction != null) data.completeFunction();
            }
        },

        enabled: function() {
            var $this = $(this),
            data = $this.data('eraser');

            if (data && data.enabled) {
                return true;
            }
            return false;
        },

        enable: function() {
            var $this = $(this),
            data = $this.data('eraser');

            if (data) {
                data.enabled = true;
            }
        },

        disable: function() {
            var $this = $(this),
            data = $this.data('eraser');

            if (data) {
                data.enabled = false;
            }
        },

        size: function(value) {
            var $this = $(this),
            data = $this.data('eraser');

            if (data && value) {
                data.size = value;
                data.ctx.lineWidth = value;
            }
        },

        reset: function() {
            var $this = $(this),
            data = $this.data('eraser');

            if (data) {
                data.ctx.globalCompositeOperation = 'source-over';
                data.ctx.drawImage(data.source, 0, 0, data.w, data.h);
                data.ctx.globalCompositeOperation = 'destination-out';
                var n = data.numParts;
                while (n--) data.parts[n] = 1;
                data.ratio = 0;
                data.complete = false;
                data.touchDown = false;
            }
        },

        progress: function() {
            var $this = $(this),
            data = $this.data('eraser');

            if (data) {
                return data.ratio / data.numParts;
            }
            return 0;
        }

    };

    $.fn.eraser = function(method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === 'object' || !method) {
            return methods.init.apply(this, arguments);
        } else {
            $.error('Method ' + method + ' does not yet exist on jQuery.eraser');
        }
    };
})(jQuery);