///-codeFile-//////////////////////////////////////////////////////////////////
// Support.js
//
// Written by Doug Greenall (douggreenall.co.uk)
// Copyright (c) 2008 Doug Greenall
//
// Feel free to use this code in any of your own personal projects but please
// leave this notice and my details intact. This code may not be used for any
// commercial projects without explicit permission
///////////////////////////////////////////////////////////////////////////////


///-code-//////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
window.MSIE = 0;
window.IsIE6 = false;
window.WebKit = (navigator.userAgent.toLowerCase().indexOf('webkit') > -1);


if (navigator.appVersion.indexOf('MSIE') > -1) {
    try { window.MSIE = parseFloat(navigator.appVersion.split('MSIE')[1]); }
    catch (e) { window.MSIE = 0; }

    window.IsIE6 = (window.MSIE >= 6.0 && window.MSIE < 7.0);
}


///-function-//////////////////////////////////////////////////////////////////
// wGet
///////////////////////////////////////////////////////////////////////////////
function wGet(ID) { return window.document.getElementById(ID); }


///-class-/////////////////////////////////////////////////////////////////////
// Vector2D
///////////////////////////////////////////////////////////////////////////////
function Vector2D(X, Y) {
    ///-data-//////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////

    this._x = X;
    this._y = Y;


    ///-arithmetic-////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////

    this.AddVal = function(Value) { this._x += Value; this._y += Value; return this; };
    this.SubVal = function(Value) { this._x -= Value; this._y -= Value; return this; };
    this.MulVal = function(Value) { this._x *= Value; this._y *= Value; return this; };
    this.DivVal = function(Value) {
        if (Value) {
            this._x /= Value;
            this._y /= Value;
        }

        return this;
    };


    this.AddVec = function(Vector) { this._x += Vector._x; this._y += Vector._y; return this; };
    this.SubVec = function(Vector) { this._x -= Vector._x; this._y -= Vector._y; return this; };
    this.MulVec = function(Vector) { this._x *= Vector._x; this._y *= Vector._y; return this; };
    this.DivVec = function(Vector) {
        if (Vector._x && Vector._y) {
            this._x /= Vector._x;
            this._y /= Vector._y;
        }

        return this;
    };

    this.MulMat = function(Matrix) {
        var thisClone = this.Clone();

        this._x = thisClone._x * Matrix._values[0][0] + thisClone._y * Matrix._values[0][1];
        this._y = thisClone._x * Matrix._values[1][0] + thisClone._y * Matrix._values[1][1];

        delete thisClone;

        return this;
    };

    this.Equals = function(Vector) {
        return (this._x === Vector._x && this._y === Vector._y);
    };


    ///-methods-///////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////

    this.toString = function() { return this._x + 'x + ' + this._y + 'y'; };
    this.Clone = function() { return new Vector2D(this._x, this._y); };

    this.GetXInt = function() { return Math.round(this._x); };
    this.GetYInt = function() { return Math.round(this._y); };

    this.GetXPxl = function() { return Math.round(this._x) + 'px'; };
    this.GetYPxl = function() { return Math.round(this._y) + 'px'; };

    this.Length = function() {
        return Math.sqrt(Math.pow(this._x, 2) + Math.pow(this._y, 2));
    };

    this.Swap = function() {
        var temp = this._x;

        this._x = this._y;
        this._y = temp;

        return this;
    };

    this.Abs = function() { this._x = Math.abs(this._x); this._y = Math.abs(this._y); return this; };
    this.Round = function() { this._x = Math.round(this._x); this._y = Math.round(this._y); return this; };
    this.AngleSigned = function(Vector) { return Math.atan2(Vector._x, Vector._y) - Math.atan2(this._x, this._y); };
}


///-class-/////////////////////////////////////////////////////////////////////
// MouseTracker
///////////////////////////////////////////////////////////////////////////////
function MouseTracker() {
    ///-data-//////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////

    var This = this;

    this._buttonDown = false;

    this._position = new Vector2D(0, 0);
    this._lastPosition = new Vector2D(0, 0);
    this._offset = new Vector2D(0, 0);

    this._timer = 0;
    this._acceleration = new Vector2D(0, 0);
    this._stopSelect = false;

    this._mouseUp = null;
    this._mouseDown = null;
    this._mouseMove = null;


    ///-methods-///////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////

    this.GetMousePosition = null;

    this.MouseUp = function(Event) {
        this._buttonDown = false;

        this.AllowSelect();

        if (this._mouseUp)
            this._mouseUp(Event);
    };

    this.MouseDown = function(Event) {
        this._buttonDown = true;

        if (this._mouseDown)
            this._mouseDown(Event);
    };

    this.MouseMove = function(Event) {
        ++this._timer;

        delete this._lastPosition;
        this._lastPosition = this._position.Clone();

        delete this._position;
        this._position = this.GetMousePosition(Event);

        this._offset.AddVec(this._position).SubVec(this._lastPosition);

        delete this._acceleration;
        this._acceleration = this._offset.Clone().DivVal(this._timer);

        if (window.opera && this._buttonDown && this._stopSelect) {
            try { wGet('operaNoSelect').focus(); }
            catch (e) { }
        }

        if (this._mouseMove)
            this._mouseMove(Event);
    };

    this.Reset = function() {
        this._offset._x = 0;
        this._offset._y = 0;

        this._timer = 0;

        this._acceleration._x = 0;
        this._acceleration._y = 0;
    };

    this.AllowSelect = function() {
        if (this._stopSelect) {
            try {
                this._stopSelect = false;

                if (window.detachEvent) {
                    window.document.detachEvent('onselectstart', This.ReturnFalse);
                }
                else {
                    wGet('site').style.MozUserSelect = '';
                    wGet('site').style.KhtmlUserSelect = '';
                }
            }
            catch (e) { }
        }
    };

    this.StopSelect = function() {
        if (!this._stopSelect) {
            try {
                this._stopSelect = true;

                if (window.attachEvent) {
                    window.document.attachEvent('onselectstart', This.ReturnFalse);
                }
                else {
                    wGet('site').style.MozUserSelect = 'none';
                    wGet('site').style.KhtmlUserSelect = 'none';
                }
            }
            catch (e) { }
        }
    };

    this.ReturnFalse = function() {
        return false;
    };


    ///-events-////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////

    if (window.document.addEventListener) {
        window.document.addEventListener("mouseup", function(Event) { This.MouseUp(Event); }, false);
        window.document.addEventListener("mousedown", function(Event) { This.MouseDown(Event); }, false);
        window.document.addEventListener("mousemove", function(Event) { This.MouseMove(Event); }, false);
    }
    else if (window.attachEvent) {
        window.document.attachEvent("onmouseup", function(Event) {
            if (window.event)
                This.MouseUp(window.event);
            else
                This.MouseUp(Event);
        });

        window.document.attachEvent("onmousedown", function(Event) {
            if (window.event)
                This.MouseDown(window.event);
            else
                This.MouseDown(Event);
        });

        window.document.attachEvent("onmousemove", function(Event) {
            if (window.event)
                This.MouseMove(window.event);
            else
                This.MouseMove(Event);
        });
    }

    if (window.WebKit) {
        this.GetMousePosition = function(Event) {
            return new Vector2D(Event.clientX + window.document.body.scrollLeft,
                                Event.clientY + window.document.body.scrollTop);
        };
    }
    else {
        this.GetMousePosition = function(Event) {
            return new Vector2D(Event.clientX + window.document.documentElement.scrollLeft,
                                Event.clientY + window.document.documentElement.scrollTop);
        };
    }
}

