﻿
window.$bcglobal = {
    $originalSize: { width: 0, top: 0 },
    $zoomValue: 1.0,
    $thumbimg: null,
    $img: null,
    $cutter: null
};
$.extend(
    $.fn, {
        ///<summary>
        /// fetch css value
        ///</summary>
        ///<param name="c">style name</param>
        f: function(c) {
            return parseInt($(this).css(c));
        },
        ///<summary>
        /// preload bitmap
        ///</summary>
        ///<param name="callback">callback function, it'll be fired after the 'preload' has completed</param>
        loadBitmap: function(callback) {
            var me = this,
                  bitmapCutterHolder = new Image(),
                  src = me.attr('rel');
            bitmapCutterHolder.src = src;
            this.onCompleted = function() {
                $(me).attr('src', src);
                $bcglobal.$originalSize = { width: bitmapCutterHolder.width, height: bitmapCutterHolder.height };
                callback(src);
            };
            if ($.browser.msie) {
                if (bitmapCutterHolder.readyState == "complete") {
                    me.onCompleted();
                }
                else bitmapCutterHolder.onreadystatechange = function() {
                    if (this.readyState == "complete") {
                        me.onCompleted();
                    }
                }
            }
            else {
                bitmapCutterHolder.onload = me.onCompleted;
            }
        },
        ///<summary>
        /// zoom in or zoom out the bitmap
        ///<remarks>
        /// use the global variable 'zoomValue' as zoom rate
        ///</remarks>
        ///</summary>
        scaleBitmap: function() {
            return this.each(function() {
                var me = $(this),
                      os = $bcglobal.$originalSize,
                      zoomValue = $bcglobal.$zoomValue;

                me.hide();
                if (os.width > 0 && os.height > 0) {
                    me.height(os.height * zoomValue)
                          .width(os.width * zoomValue);
                }
                var p = me.parent(),
                      w = me.width(),
                      h = me.height(),
                      t = (p.height() - h) / 2,
                      l = (p.width() - w) / 2;
                me.css({ 'top': t, 'left': l }).show();
                $('.jquery-bitmapcutter-info').html(w + ' : ' + h);
            });
        },
        ///<summary>
        /// resize, drag and drop
        ///</summary>
        ///<param name="setting">parameters, include limited value(left and top),condition and callback function</param>
        dragndrop: function(setting) {
            var ps = $.fn.extend({
                limited: {
                    lw: { min: 0, max: 100 },
                    th: { min: 0, max: 100 }
                },
                handler: null,
                callback: function(e) { }
            }, setting);
            var dragndrop = {
                drag: function(e) {
                    var d = e.data.d;
                    var p = {
                        left: Math.min(Math.max(e.pageX + d.left, ps.limited.lw.min), ps.limited.lw.max),
                        top: Math.min(Math.max(e.pageY + d.top, ps.limited.th.min), ps.limited.th.max),
                        target: d.target
                    };
                    ps.callback(p);
                },
                drop: function(e) {
                    $().unbind('mousemove', dragndrop.drag).unbind('mouseup', dragndrop.drop);
                }
            };
            return this.each(function() {
                if (ps.handler == null) { ps.handler = $(this) };
                var handler = (typeof ps.handler == 'string' ? $(ps.handler) : ps.handler);
                handler.bind('mousedown', function(e) {
                    var data = {
                        target: $(this),
                        left: $(this).f('left') - e.pageX,
                        top: $(this).f('top') - e.pageY
                    };
                    $().bind('mousemove', { d: data }, dragndrop.drag).bind('mouseup', dragndrop.drop);
                });
            });
        },
        ///<summary>
        /// bitmap cutter, main function
        ///</summary>
        ///<param name="setting">parameters</param>
        bitmapCutter: function(settings) {
            var lang = {
                zoomout: 'Zoom out',
                zoomin: 'Zoom in',
                original: 'Original size',
                clockwise: 'Clockwise rotation({0} degrees)',
                counterclockwise: 'Counterclockwise rotation({0} degrees)',
                generate: '生成头像',
                process: 'Please wait, transaction is processing......',
                left: 'Left',
                right: 'Right',
                up: 'Up',
                down: 'Down'
            };
            var ps = $.fn.extend({
                src: '',
                renderTo: $(document.body),
                holderSize: { width: 350, height: 250 },
                cutterSize: { width: 70, height: 70 },
                zoomStep: 0.05,
                zoomIn: 2.0,
                zoomOut: 0.05,
                rotateAngle: 90,
                //pixel
                moveStep: 80,
                onGenerated: function(src) { },
                lang: lang
            }, settings);

            //fill parameters
            ps.lang = $.extend(lang, ps.lang);
            ps.lang.clockwise = ps.lang.clockwise.format(ps.rotateAngle);
            ps.lang.counterclockwise = ps.lang.counterclockwise.format(ps.rotateAngle);
            ///<sammary>
            /// zoom interface
            ///</sammary>
            ///<param name="zv">current zoom value</param>
            function izoom(zv) {
                $bcglobal.$zoomValue = zv;
                $bcglobal.$img.scaleBitmap($bcglobal.$zoomValue);
                $bcglobal.$thumbimg.scaleBitmap($bcglobal.$zoomValue);
                scissors.createThumbnail();
            }
            ///<sammary>
            /// image rotation interface
            ///</sammary>
            ///<param name="angle">rotate angle(degree)</param>
            function irotate(angle) {
                var img = $bcglobal.$img,
                  thumbimg = $bcglobal.$thumbimg,
                  zoomValue = $bcglobal.$zoomValue,
                //Use 'rel' but not 'src',  this helps to make sure that the 'src' attribute was not start with 'http://localhost:8888/...'(msie)
                  src = img.attr('rel');
                $.ajax({
                url: 'http://res.incool.com/proxy/scissors.ashx',
                    dataType: 'json',
                    data: { action: 'RotateBitmap', src: src, angle: angle, t: Math.random() },
                    error: function(msg) {
                        alert('rotate failed!');
                    },
                    success: function(json) {
                        if (json.msg == 'success') {
                            $bcglobal.$originalSize = json.size;
                            //clear cache of img
                            src += '?t=' + Math.random();
                            img.attr('src', src).scaleBitmap();
                            thumbimg.attr('src', src).scaleBitmap();
                            scissors.createThumbnail();
                        }
                        else {
                            alert(json.msg);
                        }
                    }
                });
            }
            ///<sammary>
            /// image movement
            ///</sammary>
            ///<param name="direction">move direction(left, up, right, down)</param>
            function imove(direction) {
                var thumbimg = $bcglobal.$thumbimg,
                      img = $bcglobal.$img,
                      cutter = $bcglobal.$cutter,
                      w = img.width(),
                      h = img.height(),
                      l = img.f('left'),
                      t = img.f('top');

                if (w <= ps.holderSize.width && h <= ps.holderSize.height) {
                    return;
                }
                var limited = {
                    left: { min: Math.min(ps.holderSize.width - w, 0), max: Math.max(ps.holderSize.width - w, 0) },
                    top: { min: Math.min(ps.holderSize.height - h, 0), max: Math.max(ps.holderSize.height - h, 0) }
                };
                /*
                * it's really a weird thing that i cant use '
                *  img.animate({
                *       d: v
                *    }, function() {
                *       thumbimg.fadeIn();
                *        scissors.createThumbnail();
                *   });
                * '
                * here (d was the direction-'left' and 'top', v was the position data to be calculated!)
                * maybe it's the json to haunt me;-)
                */
                if (!img.is(':animated')) {
                    thumbimg.fadeOut();
                    var v = 0, d = {};
                    switch (direction) {
                        case 'left':
                            v = Math.min(limited.left.max, l + ps.moveStep);
                            d = { left: v };
                            break;
                        case 'right':
                            v = Math.max(limited.left.min, l - ps.moveStep);
                            d = { left: v };
                            break;
                        case 'up':
                            v = Math.min(limited.top.max, t + ps.moveStep);
                            d = { top: v };
                            break;
                        case 'down':
                            v = Math.max(limited.top.min, t - ps.moveStep);
                            d = { top: v };
                            break;
                    }

                    img.animate(d, function() {
                        thumbimg.fadeIn();
                        scissors.createThumbnail();
                    });
                }
            }
            var scissors = {
                createThumbnail: function() {
                    var thumbimg = $bcglobal.$thumbimg,
                          img = $bcglobal.$img,
                          cutter = $bcglobal.$cutter;

                    thumbimg.css({
                        'left': -cutter.f('left') + img.f('left'),
                        'top': -cutter.f('top') + img.f('top')
                    });
                },
                zoomin: function() {
                    //window.console && console.log('zoom value: %s', zoomValue);
                    izoom.call(this, Math.min($bcglobal.$zoomValue + ps.zoomStep, ps.zoomIn));
                },
                zoomout: function() {
                    //window.console && console.log('zoom value: %s', zoomValue);
                    izoom.call(this, Math.max($bcglobal.$zoomValue - ps.zoomStep, ps.zoomOut));
                },
                original: function() {
                    izoom.call(this, 1, 1);
                },
                clockwise: function() {
                    irotate.call(this, ps.rotateAngle);
                },
                counterclockwise: function(e) {
                    irotate.call(this, -ps.rotateAngle);
                },
                left: function() {
                    imove.call(this, 'left');
                },
                up: function() {
                    imove.call(this, 'up');
                },
                right: function() {
                    imove.call(this, 'right');
                },
                down: function() {
                    imove.call(this, 'down');
                }
            };
            ps.renderTo = (typeof ps.renderTo == 'string' ? $(ps.renderTo) : ps.renderTo);

            var $cl = $('<div class="jquery-bitmapcutter-cl" onselectstart="return false;"></div>').appendTo(ps.renderTo);
            var $cr = $('<div class="jquery-bitmapcutter-cr" style="display:none"></div>').appendTo(ps.renderTo);

            //bitmap holder
            var $holder = $('<div class="jquery-bitmapcutter-holder jquery-loader" />')
                                    .css(ps.holderSize)
                                        .appendTo($cl);

            //options
            var $opts = $('<div class="jquery-bitmapcutter-opts" >' +
                                    '<div class="r1c1"><a href="javascript:void(0)" onfocus="this.blur()" class="up">&nbsp</a></div>' +
                                    '<div class="r2c1">' +
                                        '<a href="javascript:void(0)" onfocus="this.blur()" class="zoomout">&nbsp</a>' +
                                        '<a href="javascript:void(0)" onfocus="this.blur()" class="zoomin">&nbsp</a>' +
                                        '<a href="javascript:void(0)" onfocus="this.blur()" class="left">&nbsp</a>' +
                                        '<a href="javascript:void(0)" onfocus="this.blur()" class="original">&nbsp</a>' +
                                        '<a href="javascript:void(0)" onfocus="this.blur()" class="right">&nbsp</a>' +
                                        '<a href="javascript:void(0)" onfocus="this.blur()" class="counterclockwise" style="display:none">&nbsp</a>' +
                                        '<a href="javascript:void(0)" onfocus="this.blur()" class="clockwise" style="display:none">&nbsp</a>' +
                                    '</div>' +
                                     '<div class="r3c1"><a href="javascript:void(0)" onfocus="this.blur()" class="down">&nbsp</a></div>' +
                                '</div>').insertAfter($holder);

            $opts.css('width', ps.holderSize.width)
                        .find('div.r2c1>a:eq(0)')
                            .css('margin-left', (ps.holderSize.width - (16 + 6) * 7 + 3) / 2);

            //informations of bitmap
            var $info = $('<div title="Size Of Bitmap" class="jquery-bitmapcutter-info" style="display:none" />')
                                .insertAfter($opts)
                                    .css('width', ps.holderSize.width);

            //cutter
            var $cutter = $('<div class="jquery-bitmapcutter-cutter" >&nbsp</div>')
                                    .css(ps.cutterSize)
                                        .css({
                                            'opacity': .4,
                                            'left': (ps.holderSize.width - ps.cutterSize.width) / 2,
                                            'top': (ps.holderSize.height - ps.cutterSize.height) / 2
                                        }).appendTo($holder);
            //initialize zoom value
            $bcglobal.$zoomValue = 1;

            //image
            var $img = $('<img alt="" rel="' + ps.src + '" />')
                                        .appendTo($holder);

            //thumbnail
            var $thumbimg = $('<img alt="" rel="' + ps.src + '" />')
                                        .appendTo(
                                            $('<div class="jquery-bitmapcutter-thumbnail" />')
                                                .css(ps.cutterSize)
                                                    .appendTo($cr)
                                                );

            var $generate = $('<a href="javascript:void(0)" class="generate" onfocus="this.blur()" >' + ps.lang.generate + '</a>')
                                        .appendTo($cr);

            var $newimg = $('<img class="jquery-bitmapcutter-newimg" alt="" src="" />')
                                        .appendTo($cr).hide();

            var $processed = $('<div class="process">' + ps.lang.process + '</div>')
                                            .hide()
                                                .appendTo($cr);

            $img.loadBitmap(function(e) {
                $img.scaleBitmap();
                $holder.removeClass('jquery-loader');

                var ks = {
                    k37: 'left',
                    k38: 'up',
                    k39: 'right',
                    k40: 'down',
                    k45: 'zoomout',
                    k61: 'zoomin'
                };

                $().keypress(function(e) {
                    var k = (e.keyCode || e.which);
                    //window.console && console.log('key code: %s', k);
                    if ((k >= 37 && k <= 40) || k == 45 || k == 61) {
                        var func = eval('scissors.' + eval('(ks.k' + k + ')') + '');
                        func();
                    }
                });

                $thumbimg.attr('src', $img.attr('src')).scaleBitmap();

                $opts.find('a').each(function() {
                    var me = $(this), c = me.attr('class');
                    me.attr('title', eval('(ps.lang.' + c + ')'))
                        .bind('click', eval('(scissors.' + c + ')'));
                });

                $cutter.dragndrop({
                    limited: {
                        lw: { min: 0, max: ps.holderSize.width - ps.cutterSize.width },
                        th: { min: 0, max: ps.holderSize.height - ps.cutterSize.height }
                    },
                    callback: function(e) {
                        $cutter.css({
                            left: e.left,
                            top: e.top
                        });
                        scissors.createThumbnail();
                    }
                });

                $('#btnGenerate').click(function() {
                    var me = $(this);

                    me.fadeOut();
                    $opts.fadeOut();
                    $cutter.fadeOut();
                    $info.hide();
                    $processed.fadeIn();
                    $.ajax({
                        url: 'http://res.incool.com/proxy/scissors.ashx',
                        dataType: 'jsonp',
                        type: 'get',
                        data: {
                            action: 'GenerateBitmap',
                            src: ps.src.replace('http://res.incool.com',''),
                            sortname:$('#btnGenerate').attr('ref'),
                            zoom: $bcglobal.$zoomValue,
                            x: $thumbimg.f('left'),
                            y: $thumbimg.f('top'),
                            width: ps.cutterSize.width,
                            height: ps.cutterSize.height,
                            t: Math.random()
                        },
                        error: function(err) {
                            alert('cant generate it!');
                        },
                        success: function(json) {
                            if (json.msg == 'success') {
                                me.fadeIn();
                                $opts.fadeIn();
                                $cutter.fadeIn();
                                $info.show();
                                $processed.fadeOut();
                                $newimg.attr('src', json.src).show();
                                ps.onGenerated(json.src);
                            }
                            else {
                                alert(json.msg);
                            }
                        }
                    });
                });
                $bcglobal.$cutter = $cutter;
                $bcglobal.$img = $img;
                $bcglobal.$thumbimg = $thumbimg;
            });
        }
    });
///<summary>
/// text format(same as c-sharp,
/// e.g.: 'example {0}: {2}'.format('A','none'))
/// output: example A: none
///</summary>
    String.prototype.format = function() {
        var args = arguments;
        return this.replace(/{(\d{1})}/g, function() {
            return args[arguments[1]];
        });
    };