/**
 * coded by philo
 * full xhtml content supported
 *
 */
(function($) {
    $.fn.drillset = function(options) {
        var defaults = {
            center: 200,
            pxPerMm: 1,
            side: 'right',
            sclX: 1,
            sclY: 1
        };
        options = $.extend(false, defaults, options);
        new DrillSet($(this), options);
    };

    function DrillSet(element, options) {
        this.init(element, options);
    }
    DrillSet.prototype = {
        init: function(element, options) {
            this.element = element;
            this.options = options;
            this.options.scalarStepDegree = 360 / this.options.scalars.length;
            this.values = {};
            for (var i = 1; i <= 4; i++) {
                this.values[i] = {
                    'x': '',
                    'y': ''
                }
                var pointEl = $('#dw' + i);
                pointEl.draggable({
                    appendTo: $('#drillset'),
                    containment: 'parent'
                });
                pointEl.bind('dragstop', {self: this}, function(e, position) {
                    e.data.self.endDrag($(this), position);
                });
            }
            this.update();
            this.element.bind('click', {self: this}, function(e) {
                var offset = $(this).offset();
                e.data.self.addDrillWhole(e.pageX - offset.left, e.pageY - offset.top);
            });
            // add events
            $('#drillset_control div.delete input[dw]').bind('click', {self: this}, function(e) {
                var index = $(this).attr('dw');
                e.data.self.removeDrillWhole(index);
                return false;
            });
            $('#drillset_control ul.drillset_fields input[type=text]').bind('change', {self: this}, function(e) {
                e.data.self.update();
            });
            $('#drillset_control input[type=text]').bind('focus', {self: this}, function(e) {
                this.select();
            });
            $('#drillset_control ul.drillset_fields a').bind('click', {self: this}, function(e) {
                e.data.self.update();
            });
            $('#drillset').bind('mousemove', {self: this}, function(e) {
                var offset = $(this).offset();
                var xCoord = (e.pageX - offset.left - e.data.self.options.center) / e.data.self.options.pxPerMm;
                var yCoord = ((e.data.self.options.center - e.pageY - offset.top) + e.data.self.options.center) / e.data.self.options.pxPerMm;
                e.data.self.updatePosition(xCoord.toFixed(1), yCoord.toFixed(1));
            });
        },
        update: function() {
            var empty = [];
            for (var i = 1; i <= 4; i++) {
                var xInput = $('#d' + i + 'x_' + this.options.side + '_field');
                var yInput = $('#d' + i + 'y_' + this.options.side + '_field');
                $('input[name=drill_' + i + '_delete_field]').val(0);
                var xVal = xInput.val();
                var yVal = yInput.val();
                if (xVal && yVal) {
                    var xValPx = this.options.center + (xVal * this.options.pxPerMm);
                    var yValPx = this.options.center - (yVal * this.options.pxPerMm);
                    if (this.checkPoint(
                        (xVal * this.options.pxPerMm) / this.options.sclX,
                        (yVal * this.options.pxPerMm) / this.options.sclX
                    )) {
                        this.values[i] = {x: xValPx, y: yValPx};
                        if (empty.length) {
                            var m = empty.shift();
                            $('#d' + m + 'x_' + this.options.side + '_field').val(xVal);
                            $('#d' + m + 'y_' + this.options.side + '_field').val(yVal);
                            $('input[name=drill_' + m + '_delete_field]').val(0);
                            $('input[name=drill_' + i + '_delete_field]').val(1);
                            xInput.val('');
                            yInput.val('');
                            this.values[m] = {x: xValPx, y: yValPx};
                            this.values[i] = {x: '', y: ''};
                            empty.push(i);
                        }
                    } else if (!this.values[i].x || !this.values[i].y) {
                        empty.push(i);
                    } else {
                        // set point back to old position
                        var xVar = ((this.values[i].x - this.options.center) / this.options.pxPerMm).toFixed(1);
                        var yVar = ((this.options.center - this.values[i].y) / this.options.pxPerMm).toFixed(1);
                        $('#d' + i + 'x_' + this.options.side + '_field').val(xVar);
                        $('#d' + i + 'y_' + this.options.side + '_field').val(yVar);
                    }
                } else {
                    this.values[i] = {};
                    $('input[name=drill_' + i + '_delete_field]').val(1);
                    empty.push(i);
                }
            }
            this.drawPoints();
        },
        drawPoints: function() {
            for (var i = 1; i <= 4; i++) {
                var values = this.values[i];
                var pointEl = $('#dw' + i);
                if (values.x && values.y) {
                    pointEl.css('display', 'block');
                    pointEl.css('top', values.y + 'px');
                    pointEl.css('left', values.x + 'px');
                } else {
                    pointEl.css('display', 'none');
                }
            }
        },
        endDrag: function(pointEl, position) {
            var index = pointEl.attr('id').substr(pointEl.attr('id').length - 1);
            var x = (position.position.left - this.options.center);
            var y = (this.options.center - position.position.top);
            var mmX = x / this.options.pxPerMm;
            var mmY = y / this.options.pxPerMm;
            if (this.checkPoint(x / this.options.sclX, y / this.options.sclY)) {
                $('#d' + index + 'x_' + this.options.side + '_field').val(mmX.toFixed(1));
                $('#d' + index + 'y_' + this.options.side + '_field').val(mmY.toFixed(1));
            }
            this.update();
        },
        checkPoint: function(x, y) {
            var distanceToCenter = this.getDistance(0, 0, x, y);
            // get angle for point
            var angle = this.getAngle(0, 0, x, y);
            if (y >= 0) {
                angle = (x < 0) ? 90 + (90 + angle) : angle;
            } else {
                angle = (x < 0) ? 180 + Math.abs(angle) : 360 - angle;
            }
            // get scalar for angle
            var index = Math.round(angle / this.options.scalarStepDegree);
            return (distanceToCenter <= (this.options.scalars[index] / 100) * this.options.pxPerMm);
        },
        getAngle: function(x1, y1, x2, y2) {
            var a = (y1 - y2);
            var b = (x1 - x2);
            //var c = Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));
            // ? = arccos [(-a2 + b2 + c2)/(2 b c)]
            //var alphaRad = Math.acos((Math.pow(b, 2) + Math.pow(c, 2) - Math.pow(a, 2)) / (2 * b * c));
            var alphaRad = Math.atan(a / b);
            // [winkel(DEG)=winkel(RAD)*(360°/2*pi)]
            var alpha = ((y1 > y2) ? alphaRad * ( -1) : alphaRad) * (180 / Math.PI);
            return alpha;
        },
        getDistance: function(x1, y1, x2, y2) {
            var a = (y1 - y2);
            var b = (x1 - x2);
            return Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));
        },
        addDrillWhole: function(xPos, yPos) {
            var pointEl = false;
            for (var i = 1; i <= 4; i++) {
                if ($('#dw' + i).css('display') == 'none') {
                    pointEl = $('#dw' + i);
                    break;
                }
            }
            if (pointEl) {
                pointEl.css('display', 'block');
                var pos = {'position': {'left': xPos, 'top': yPos}};
                this.endDrag(pointEl, pos);
            }
        },
        removeDrillWhole: function(index) {
            //if ($('ul.drillset_fields li:has(input[type=text][value=])').length >= 2) {
            //    return;
            //}
            $('#d' + index + 'x_' + this.options.side + '_field').val('');
            $('#d' + index + 'y_' + this.options.side + '_field').val('');
            this.update();
        },
        updatePosition: function(x, y) {
            $('#drillset_control .x-info').html(x);
            $('#drillset_control .y-info').html(y);
        }
    }
})(jQuery);