// (c) Wi2Geo 2009
// Magic Scanner Web Interface
// v.4.0 stable 9.07.2009
function Wi2GeoScanner(key, onNotInstalled, operaSupport, onOldVersionMessage)
{
    this.apiKey = key ? key : '';
    this.vNeed  = '2.2';
    this.vCurr  = '0.0';
    this.fr     = false;
    this.after  = false;
    this.point  = false;
    this.status = '';
    this.nia    = 0;
    this.niv    = 0;

    this.canScanJS = 1;
    this.urlJS  = 'http://localhost:8889/js-data/';

    this.url    = 'http://localhost:8889/embedded-data/';
    this.api    = 'http://api2.wi2geo.ru/';
    this.tmi    = false;

    this.operaScan = operaSupport ? operaSupport : false;
    this.onOldVersionMessage = onOldVersionMessage ? onOldVersionMessage : false;

    this.onNotInstalled = onNotInstalled ? onNotInstalled : false;
    if (navigator.userAgent.indexOf('Mac') != -1)
//        this.distr = 'http://www.wi2geo.ru/updates/MagicScanner/Wi2GeoMagic.zip';
        this.distr = 'http://api.wi2geo.ru/downloads/Wi2Geo.MagicScanner.dmg';
    else
//        this.distr = 'http://www.wi2geo.ru/updates/MagicScanner/Wi2Geo.MagicScanner.Installer.msi';
        this.distr = 'http://api.wi2geo.ru/downloads/Wi2Geo.MagicScanner.msi';

    var me = this;

    window.wi2geoScan = this;

    //xPath prototype functions
    if(window.XMLDocument && document.implementation.hasFeature("XPath", "3.0") && !XMLDocument.prototype.selectNodes)
    {
        XMLDocument.prototype.selectNodes = function(cXPathString, xNode)
        {
            if(!xNode) {xNode = this;}
            var oNSResolver = this.createNSResolver(this.documentElement);
            var aItems = this.evaluate(cXPathString, xNode, oNSResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
            var aResult = [];
            for(var i=0; i<aItems.snapshotLength; i++)
                aResult[i] =  aItems.snapshotItem(i);
            return aResult;
        };

        XMLDocument.prototype.selectSingleNode = function(cXPathString, xNode)
        {
            if(!xNode){xNode = this;}
            var oNSResolver = this.createNSResolver(this.documentElement);
            var xItems = this.evaluate(cXPathString, xNode, oNSResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
            if (xItems.snapshotLength>0) return xItems.snapshotItem(0);
            return null;
        };

        Element.prototype.selectNodes = function(cXPathString)
        {
            if(this.ownerDocument.selectNodes)
                return this.ownerDocument.selectNodes(cXPathString, this);
            else{throw "For XML Elements Only";}
        };

        Element.prototype.selectSingleNode = function(cXPathString)
        {
            if(this.ownerDocument.selectSingleNode)
                return this.ownerDocument.selectSingleNode(cXPathString, this);
            else{throw "For XML Elements Only";}
        };
    };

    //interface functions
    this.scan = function(after)
    {
        this.after = typeof(after)=='function' ? after : false;
        this.point = false;
        if (window.opera)
        {
            if(this.operaScan) this.operaScan();
            else if(this.after) this.after(false);
            return;
        }
        if(me.nia==0) this.tmi = window.setTimeout(this.onInstall,3000);
        this.startScan();
    };

    this.fix = function(lat, lng, zoom, after)
    {
        this.point = lng ? {'lat':lat,'lng':lng,'zoom':zoom} : lat;
        this.after = typeof(after)=='function' ? after : false;
        if (window.opera && this.operaScan) this.operaScan();
        else this.startScan();
    };

    //inner functions

    this.startScan = function()
    {
        if (me.canScanJS)
        {
            me.createScriptElement(me.urlJS+'?rand='+parseInt(Math.random()*100000));
        }
        else
        {
            me.initFrame();
            me.addEvent();
            me.getRequest(me.url+'?rand='+parseInt(Math.random()*100000),'local');
        }
    };

    this.local = function(res)
    {
        if (!res)
        {
            me.onInstall();
            return me.onExit();
        }
        var x = me.createXMLObject(res);
        var node = x.selectSingleNode('MagicScanner');
        me.vCurr = node ? node.getAttribute('Version') : '0.0';
        if(!me.checkVersion()  && !me.oldVersionRes)
        {
            me.oldVersionRes = res;
            me.nia = 0;
            me.onInstall();
//            return me.onExit();
        }
        node = x.selectSingleNode('MagicScanner/data');
        if(me.point)
        {
            me.postRequest(me.api+'feedback','feedback',{
                           'api_key' : me.apiKey,
                           'doctype' : 'embedded-xml',
                           'data'    : node.textContent || node.text,
                           'newlat'  : me.point.lat,
                           'newlng'  : me.point.lng,
                           'zoom'    : me.point.zoom
            });
        }
        else
        {
            me.postRequest(me.api+'getlocation','getlocation',{
                           'api_key' : me.apiKey,
                           'doctype' : 'embedded-xml',
                           'data'    : node.textContent || node.text,
                           'version' : '1.2'
            });
        }
    };

    this.getlocation = function(res)
    {
        if (!res) return me.onExit();
        var x = me.createXMLObject(res);
        if(me.after)
        {
            me.after({'lat'        : me.getNodeText(x,'wi2geo/iamhere/latitude')     ,
                      'lng'        : me.getNodeText(x,'wi2geo/iamhere/longitude')    ,
                      'type'       : me.getNodeText(x,'wi2geo/iamhere/pos_type_text'),
                      'typenum'    : me.getNodeText(x,'wi2geo/iamhere/pos_type')     ,
                      'precision'  : me.getNodeText(x,'wi2geo/iamhere/precision')    ,

                      'building'   : { 'street'  : me.getNodeText(x,'wi2geo/nearest/building/street') || me.getNodeText(x,'wi2geo/nearest/street/name'),
                                       'address' : me.getNodeText(x,'wi2geo/nearest/building/address') || me.getNodeText(x,'wi2geo/nearest/building/name') },

                      'metro'      : { 'name'    : me.getNodeText(x,'wi2geo/nearest/metro/name'),
                                       'distance': me.getNodeText(x,'wi2geo/nearest/metro/distance') },

                      'city'       : { 'name'    : me.getNodeText(x,'wi2geo/nearest/city/name'),
                                       'country' : me.getNodeText(x,'wi2geo/nearest/country/name')    },

                      'xml'        : x,
                      'text'       : res
                    });
            me.after = null;
        }
        me.onExit();
    };

    this.getNodeText = function(x,path)
    {
        var node = x.selectSingleNode(path);
        if (node)
        {
            node = node.textContent || node.text;
            return (node=='null') ? '' : node;
        }
        return '';
    }

    this.feedback = function(res)
    {
        if (!res) return me.onExit();
        if (me.after)
        {
            me.after(me.createXMLObject(res),res);
            me.after = null;
        }
    };

    this.checkVersion = function()
    {
        if (me.niv==1) return true;
        me.niv = 1;
        var n = me.vNeed.split('.');
        n = parseInt(n[0]+''+n[1]);
        var e = me.vCurr.split('.');
        if(e.length>1) e = parseInt(e[0]+''+e[1]);
        else return false;
        return (e>=n);
    };

    this.onInstall = function()
    {
        if (me.canScanJS && !window.location.href.indexOf('svyaznoy'))
        {
            me.canScanJS = 0;
            me.startScan();
            me.tmi = window.setTimeout(me.onInstall,3000);
            return;
        }
        if (me.vCurr!='0.0')
        {
            window.noMScanner = 2;
        }
        else
        {
            if (me.after) me.after();
            window.noMScanner = 1;
        }

        if (me.onNotInstalled)
        {
            me.nia++;
            if (me.vCurr!='0.0')
                me.onNotInstalled(me.distr, me.nia, me.vCurr, me.vNeed);
            else
                me.onNotInstalled(me.distr, me.nia);
        }
        else
        {
            if ((navigator.userAgent.indexOf('Mac') == -1) && ((document.all && !window.opera) || navigator.javaEnabled()))
               me.installApplet();
            else
                me.installDistr();
        }
    };

    this.installApplet = function()
    {
        if (me.nia>0) return;

        if (!window.installApplet)
        {
            window.installApplet = new CInstallApplet(me.startScan, me.installDistr);
            window.installApplet.install();
        }
    };

    this.installDistr = function()
    {
        if(me.nia==0)
        {
            if(me.vCurr!='0.0')
            {
                if (confirm('Wi2Geo Magic Scanner version '+me.vCurr+' is out of support. Download the last version now?'))
                {
                    window.location.href = me.distr;
                }
                else if (me.onOldVersionMessage)
                {
                    me.nia = 1;
                    me.onOldVersionMessage(me.vCurr);
                }
                else me.nia = 1;
            }
            else
            {
                if (confirm('Wi2Geo Magic Scanner is not installed. Download it now?'))
                    window.location.href = me.distr;
                else me.nia = 1;
            }
        }
    };

    this.onExit = function()
    {
        me.clearEvent();
        if(me.after)
        {
            me.after();
            me.after = null;
        }
        return false;
    };

    //core functions
    this.getRequest = function(url,after)
    {
        me.status = after;
        me.fr.src = url;
    };

    this.postRequest = function(url,after,args)
    {
        me.status  = after;

        if (me.canScanJS)
        {
            args.doctype = 'js-xml';
            var sep = '?';
            for (var i in args)
            {
                url += sep+i+'='+args[i];
                sep = '&';
            }
            me.createScriptElement(url);
            return;
        }

        var doc    = me.fr.contentDocument ? me.fr.contentDocument : me.fr.contentWindow.document.documentElement;
        var body   = doc.getElementsByTagName('body')[0];
        var canApp = true
        if (!doc.createElement)
        {
           canApp = false;
           doc = document;
        }

        body.innerHTML = '';
        var f = doc.createElement('form');
        f.method = 'post';
        f.action = url;
        //confirm(url);
        var val = '';

        if (canApp)
        {
            for(var i in args)
            {
                val = doc.createElement('input');
                val.type = 'hidden';
                val.value = args[i];
                val.name = i;
                f.appendChild(val);
            }
            body.appendChild(f);
        }
        else
        {
            for(var i in args) val += '<input type="hidden" name="'+i+'" value="'+args[i]+'">';
            f.innerHTML = val;
            document.body.appendChild(f);
            var d = doc.createElement('div');
            d.appendChild(f);
            body.innerHTML = d.innerHTML;
            f = body.getElementsByTagName('form')[0];
        }

        f.submit();
    };

    this.initFrame = function()
    {
        this.status = 'local';
        if(!this.fr)
        {
       		this.fr = document.createElement('IFRAME');
    		if(window.navigator.appName=='Netscape')
    		{
    		    this.fr.style.width = '0px';
        	    this.fr.style.height = '0px';
        	    this.fr.style.visibility = 'hidden';
    		}
    		else this.fr.style.display = 'none';
    		document.body.appendChild(this.fr);
        }
    };

    this.addEvent = function()
    {
        if (this.fr.addEventListener)
            this.fr.addEventListener('load', this.responseData, false);
        else if(this.fr.attachEvent)
            this.fr.attachEvent('onload', this.responseData);
    	else
    	    this.fr.onload = this.responseData;
    };

    this.clearEvent = function()
    {
        if (me.fr.removeEventListener)
            me.fr.removeEventListener('load',me.responseData,false);
        else if (me.fr.detachEvent)
            me.fr.detachEvent('onload',me.responseData);
        else
           me.fr.onload = null;
    };

    this.ac = 0;

    this.responseData = function()
    {
        if (me.status.indexOf('response')>0)
        {
            var res = false;
            try{res = me.fr.contentWindow.name;}catch(e){}
            if(res) me.nia = 1;
            if(res && me.tmi) {window.clearTimeout(me.tmi);}
            try{me.fr.contentWindow.name = '';}catch(e){}


            if (me.status == 'localresponse' && !res)
            {
                me.ac++;
                window.clearTimeout(me.tmi);
                if (me.ac>1) me.onInstall();
                else me.startScan();
            }
            else
            {
        //        if (window.opera && res.indexOf('101'))
        //        {
        //            alert(me.status + '-' + res);
        //        }
                var func = eval('me.'+me.status.replace('response',''));
                if (func) func(res ? res : false);
            }
        }
        else
        {
            me.status += 'response';
            me.fr.contentWindow.location = 'about:blank';
        }
    };

    this.createXMLObject = function(txt)
    {

        if (document.all && !window.opera)
        {
            var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
            xmlDoc.async = "false";
            xmlDoc.loadXML(txt);
            return xmlDoc;
        }
        else
        {
            var parser = new DOMParser();
            return parser.parseFromString(txt,"text/xml");
        }
    };

    this.destroyScriptElement = function()
    {
        try{
            document.body.removeChild(me.scriptElement);
            delete(me.scriptElement);
        }catch(e){}
    };

    this.createScriptElement = function(url)
    {
        me.scriptElement = document.createElement('script');
        me.scriptElement.type = 'text/javascript';
        me.scriptElement.charset = 'utf-8';
        document.body.appendChild(me.scriptElement);
        me.scriptElement.src = url;
    };

}

function CInstallApplet(success, failed)
{
    this.onAppletInstallationFailed = function()
    {
        failed();
    };

    this.onAppletInstallationSuccessfull = function()
    {
        success();
    };

    this.install = function()
    {
            var app = (document.all && !window.opera) ?
            '<OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93" width="1" height="1" align="baseline" '+
            'codebase="http://java.sun.com/products/plugin/1.4/jinstall-14-win32.cab#Version=1,4,0,mn">'+
            '<PARAM NAME="java_code" VALUE="Wi2GeoApplet.class">'+
            '<PARAM NAME="java_archive" VALUE="http://api.wi2geo.ru/js/Wi2GeoApplet.jar">'+
            '<PARAM NAME="java_type" VALUE="application/x-java-applet">'+
            '<PARAM NAME="scriptable" VALUE="true"></OBJECT>'
            :
            '<EMBED type="application/x-java-applet" width="1" height="1" align="baseline" '+
            'code="Wi2GeoApplet.class" archive="http://api.wi2geo.ru/js/Wi2GeoApplet.jar" model="http://api.wi2geo.ru/js/Wi2GeoApplet.jar" '+
            'pluginspage="http://java.sun.com/j2se/1.4.1/download.html"><param name="java_archive" value="http://api.wi2geo.ru/js/Wi2GeoApplet.jar"/><NOEMBED>'+
            'No Java 2 SDK, Standard Edition v 1.4.1 support for APPLET!!</NOEMBED></EMBED>';

            var appletDiv = document.createElement("div");
            appletDiv.style.dislay = 'none';

            if (document.all && !window.opera)
                document.body.appendChild(appletDiv);
            else
                document.getElementsByTagName('body').item(0).appendChild(appletDiv);

            appletDiv.innerHTML = app;
     };
}

window.wi2geoScanResponse = function(res)
{
    window.wi2geoScan.nia = 1;
    if(window.wi2geoScan.tmi) window.clearTimeout(window.wi2geoScan.tmi);
    window.wi2geoScan.destroyScriptElement();
    window.wi2geoScan.local(res);
};

window.wi2geoServerResponse = function(res)
{
     window.wi2geoScan.destroyScriptElement();
     if(window.wi2geoScan.status=='feedback') window.wi2geoScan.feedback(res);
     else window.wi2geoScan.getlocation(res);
};
