/**
 * Env class does all browser/platform detection logic (as in , "Env platform this?")
 */
function Env() {}

/**
 * Return true if any of the arguments are in the user agent
 */
Env._is = function() {
    for (var i = 0; i < arguments.length; i++) {
        if (Env._ua.indexOf(arguments[i].toLowerCase()) >= 0) {
            return true;
        }
    }
    return false;
}

Env._detect = function(ua) {
    /** Normalized user agent string (all lowercase) */
    Env._ua = ua.toLowerCase();

    // Parse platform info

    /** True for Mac OS */
    Env.MAC = Env._is('mac');
    Env.MACOS10 = Env._is('mac os x');

    /** True for Windows systems */
    Env.WIN = Env._is('win');
    Env.WIN31 = Env._is('windows 3.1', 'win31');
    Env.WIN95 = Env._is('windows 95', 'win95');
    Env.WIN98 = Env._is('windows 98', 'win98');
    Env.WINME = Env._is('windows me');
    Env.WINNT = Env._is('windows nt 4.0', 'winnt');
    Env.WIN2K = Env._is('windows nt 5.0');
    Env.WINXP = Env._is('windows nt 5.1');

    // Parse browser type

    /** Browser version detected */
    Env._v = 0;

    /** True for IE */
    Env.IE = Env._is('msie');

    /** True for non-IE (mozilla variants, safari, opera , etc.) */
    Env.NS = !Env.IE;

    /** True for all safari browsers */
    Env.SAFARI = Env._is('safari');

    /** True for all safari browsers */
    Env.FIREFOX = Env._is('firefox');

    /** True for all AOL clients */
    Env.AOL = Env._is('aol');

    /** True only for netscape branded */
    Env.NETSCAPE = false;

    /** Gecko build date.  Occasionally useful for determining mozilla versions */
    Env._gd = 0;

    // Determine the browser version
    if (Env.IE) {
        Env._v = parseFloat(Env._ua.substr(Env._ua.indexOf('msie') + 4));
    } else if (Env.SAFARI) {
        Env._v = parseFloat(Env._ua.substr(Env._ua.indexOf('safari/') + 7));
    } else {
        // Parse gecko build date
        Env._gd = 0;
        if (Env._is('gecko/')) {
            Env._gd = parseInt(Env._ua.substr(Env._ua.indexOf('gecko/') + 6));
        }

        // Get the version
        if (Env._is('netscape6/')) {
            Env.NETSCAPE = true;
            Env._v = parseFloat(Env._ua.substr(Env._ua.indexOf('netscape6/') + 10));
        } else if (Env._is('netscape/')) {
            Env.NETSCAPE = true;
            Env._v = parseFloat(Env._ua.substr(Env._ua.indexOf('netscape/') + 9));
        } else if (Env._gd > 20050000) {
            Env._v = 8;
        } else if (Env._gd > 20040000) {
            Env._v = 7.2;
        } else if (Env._gd > 20020000) {
            Env._v = 7.1;
        } else if (Env._gd > 20010000) {
            Env._v = 6.2;
        }

        // Parse gecko build date
        if (Env._is('gecko/')) {
            Env._gd = parseInt(Env._ua.substr(Env._ua.indexOf('gecko/') + 6));
        }
    }

    // Parse browser type

    /** True for IE5 */
    Env.IE5 = Env.IE && (Env._v >= 5.0 && Env._v < 5.1);

    /** True for IE5.5 */
    Env.IE55 = Env.IE && (Env._v == 5.5 && Env._v < 5.6);

    /** True for IE6 */
    Env.IE6 = Env.IE && (Env._v == 6.0 && Env._v < 6.1);

    /** True for IE5+ */
    Env.IE5UP = Env.IE && (Env._v >= 5.0);

    /** True for IE5.5+ */
    Env.IE55UP = Env.IE && (Env._v >= 5.5);

    /** True for IE6+ */
    Env.IE6UP = Env.IE && (Env._v >= 6.0);

    /** True for all NS6.0+ browsers */
    Env.NS6UP = Env.NS && (Env._v >= 6.0);

    /** True for all NS6.2 browsers */
    Env.NS62 = Env.NS && (Env._v == 6.2);

    /** True for all NS6.2+ browsers */
    Env.NS62UP = Env.NS && (Env._v >= 6.2);

    /** True for NS7 */
    Env.NS7 = Env.NS && (Env._v == 7.0);

    /** True for all NS7+ browsers */
    Env.NS7UP = Env.NS && (Env._v >= 7.0);

    /** True for NS7.1 */
    Env.NS71 = Env.NS && (Env._v == 7.1);

    /** True for all NS7.1+ browsers */
    Env.NS71UP = Env.NS && (Env._v >= 7.1);

    /** True for Mozilla 1.0+ */
    Env.MOZ1UP = (!Env.NETSCAPE) && (!Env.FIREFOX) && (Env._gd >= 20020530);

    /** True for AOL 6 clients */
    Env.AOL6 = Env._is('aol 6');

    /** True for AOL 7 clients */
    Env.AOL7 = Env._is('aol 7');

    /** True for AOL 8 clients. */
    Env.AOL8 = Env._is('aol 8') || (Env._is('mac os x') && Env._is('aol/7.0'));

    /** True for AOL 7 clients */
    Env.AOL9 = Env._is('aol 9');

    /** True for AOL 9+ clients */
    Env.AOL9UP = Env.AOL9;

    /** True for AOL 8+ clients */
    Env.AOL8UP = Env.AOL8 || Env.AOL9UP;

    /** True for AOL 7+ clients */
    Env.AOL7UP = Env.AOL7 || Env.AOL8UP;

    /** True for AOL 6+ clients */
    Env.AOL6UP = Env.AOL6 || Env.AOL7UP;

    /** True for all safari browsers */
    Env.SAFARI12 = Env.SAFARI && (Env._v >= 125);
}

// Run the detection logic
Env._detect(navigator.userAgent);

// --------------------
// Plugin detection logic.  This is loosely based on a variety of scripts and
// information found on the web. Some of the more relevent URLs:
// http://webmonkey.wired.com/webmonkey/reference/javascript_code_library/wm_pluginbot/?tw=reference&category=language_extensions
// http://www.javascriptkit.com/script/script2/plugindetect.shtml
// http://www.smeenk.com/article.php?ArticleID=2
// http://www.quirksmode.org/js/flash.html
// --------------------

/**
 * Information about various well-known plugins.  The fields are as follows:
 * name -   (Mozilla detection) A string that is contained in the plugins[].description field
 * mime -   (Mozilla detection) An array of all mimetypes that the plugin must
 *          support to be recognized
 * activex - (IE detection) A list of possible activeX classIDs to use in
 *           identification.  These should be in descending version order.
 */
Env._pluginInfo = new Object();
Env._pluginInfo.wmp = {
    name: 'Windows Media',
    mime: ['application/x-mplayer2'],
    activex: [
        'WMPlayer.OCX.7',
        'WMPlayer.OCX',
        'MediaPlayer.MediaPlayer'
    ]
};
Env._pluginInfo.flash = {
    name: 'Flash',
    mime: ['application/x-shockwave-flash'],
    activex: [
        'ShockwaveFlash.ShockwaveFlash.7',
        'ShockwaveFlash.ShockwaveFlash.6',
        'ShockwaveFlash.ShockwaveFlash.5',
        'ShockwaveFlash.ShockwaveFlash'
    ]
};
Env._pluginInfo.director = {
    name: 'Shockwave',
    mime: ['application/x-director'],
    activex: ['SWCtl.SWCtl.1']
};
Env._pluginInfo.quicktime = {
    name: 'QuickTime',
    mime: ['video/quicktime'],
    activex: [
        'QuickTimeCheckObject.QuickTimeCheck.1',
        'QuickTimeCheckObject.QuickTimeCheck'
    ]
};
Env._pluginInfo.real = {
    name: 'RealPlayer',
    mime: ['audio/x-pn-realaudio-plugin'],
    activex: [
        'rmocx.RealPlayer G2 Control',
        'RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)',
        'RealVideo.RealVideo(tm) ActiveX Control (32-bit)'
    ]
};
Env._pluginInfo.svg = {
    name: 'SVG Viewer',
    mime: ['image/svg-xml'],
    activex: [
    'Adobe.SVGCtl.3',
    'Adobe.SVGCtl'
    ]
};
Env._pluginInfo.acrobat = {
    name: 'Acrobat',
    mime: ['application/pdf'],
    activex:[
        'PDF.PdfCtrl.6',
        'PDF.PdfCtrl.5',
        'PDF.PdfCtrl.4',
        'PDF.PdfCtrl'
    ]
};

// Write the VBScript method that lets us detect ActiveX objects
if (Env.IE && Env.WIN) {
    var script = [
        '<' + 'script language="VBscript">',
        'Dim Env_canDetectActiveX, Env_object',
        '',
        'Env_canDetectActiveX = 0',
        'If ScriptEngineMajorVersion >= 2 then',
        '  Env_canDetectActiveX = 1',
        'End If',
        '',
        'Function Env_activeXDetect(activeXName)',
        '  on error resume next',
        '  Env_activeXDetect = False',
        '  set Env_object = CreateObject(activeXName)',
        '  Env_activeXDetect = IsObject(Env_object)',
        '  If (err) then',
        '     Env_activeXDetect = False',
        '  End If',
        'End Function',
        '</'+'script>'
    ];
    document.write(script.join('\n'));

    // Set flag indicating activeX detection is enabled
    Env.activeXDetection = Env_canDetectActiveX;
}

/**
 * Check for a plugin. The return value is guaranteed to be >0 if the plugin
 * is installed.  And, if you're lucky, it'll be the version of the plugin.
 * However, this information is liable to be very platform dependent.  The
 * default version is 1.
 */
Env.pluginDetect = function(pluginName) {
    pluginName = pluginName.toLowerCase();
    var pi = Env._pluginInfo[pluginName];

    // Assume we fail
    var detected=0;

    // Do activeX detection if possible
    if (Env.activeXDetection) {
        // Walk through list of ProgIDs, seeing if a class can be instantiated
        for (var i = 0; i < pi.activex.length; i++) {
            detected = Env_activeXDetect(pi.activex[i]);
            if (detected) {
                // We found a class, now see if we can extract version info
                var version;
                if (Env_object) {
                    // See if versionString is defined (WMP does, not sure about other plugins)
                    version = Env_object.versionInfo;
                }
                if (!version) {
                    // Otherwise, try to pull it out of the ProgID
                    version = pi.activex[i].replace(/.*\./, '');
                }

                version = parseInt(version);
                detected = !isNaN(version) ? version : 1;
                break;
            }
            detected = 0;
        }
    } else {
        var plugins = navigator.plugins;
        var mtypes = navigator.mimeTypes;
        if (!detected && plugins && plugins.length > 1) {
            // Nothing detected yet, but plugins array looks searchable
            for (var i = 0; i < plugins.length; i++) {
                var plugin = plugins[i];
                if ((plugin.description.indexOf(pi.name) >= 0)
                        || (plugin.name.indexOf(pi.name) >= 0)) {
                    var version = '1';
                    if (pluginName == "quicktime") {
                        version = plugin.name.replace(/^[^0-9]*/,'')
                    }
                    version = parseInt(version);

                    detected = (!isNaN(version) && version) ? version : 1;
                    break;
                }
            }
        }
    }

    return detected;
}

