// add support for Array scan (ECMA 262 extension) if not already supported
if (!Array.prototype.indexOf) {
  Array.prototype.indexOf = function(elt /*, from*/) {
    var len = this.length;

    var from = Number(arguments[1]) || 0;
    from = (from < 0)
         ? Math.ceil(from)
         : Math.floor(from);
    if (from < 0)
      from += len;

    for (; from < len; from++) {
      if (from in this && this[from] === elt)
        return from;
    }
    return -1;
  };
}

var MAPSNIFF=function(){
  /*
    Created by Niall Kennedy: http://www.niallkennedy.com/

    Compare a set of known links against a visitor's browser history to determine preferred online mapping service.
    Add the appropriate map to the page.
  */
  
  this.runstate={
    link:null,
    test_elem:null,
    visitedlinks:[] // store positive matches here
  };

  this.testlinks={
    /*
      Supply a set of test links placed into provider buckets.
      urlset defines a list of links that may indicate a site visitor's usage of a particular service.
      Links should be supplied in the order of most likely usage to most quickly achieve a positive match
    */
    mappers:[
    {
      provider:'mapquest',
      urlset:[
        'http:\/\/www.mapquest.com\/',
        'http:\/\/beta.mapquest.com\/'
      ]
    },
    {
      provider:'google',
      urlset:[
        'http:\/\/maps.google.com\/',
        'http:\/\/maps.google.com\/maps'
      ]
    },
    {
      provider:'yahoo',
      urlset:[
        'http:\/\/maps.yahoo.com\/'
      ]
    },
    {
      provider:'winlive',
      urlset:[
        'http:\/\/maps.live.com\/'
      ]
    },
    {
      provider:'openstreetmap',
      urlset:[
        'http:\/\/openstreetmap.org\/',
        'http:\/\/www.openstreetmap.org\/'
      ]
    }
  ]
};

return{
  alreadyScanned:function(){
    return false;
    // usually we would scan the site cookie for our previously stored values, but we're not storing anything so you can more easily see how things work
    /*
    var maps=getCookie('mapservice');
    if ( maps!==null && maps!=="" ) {
      runstate.visitedlinks=maps.split(',');
      return true;
    }
    else {
      return false;
    }
    */
  },
  
  hasVisitedLinks:function(){
    /*
      Check to see if our scan yielded any results
    */
    if ( runstate.visitedlinks && runstate.visitedlinks.length>0 ) {
      return true;
    }
    else {
      return false;
    }
  },

  init:function(){
    /*
      Setup our link scanner runtime.
      
      Setup the test area where links will be inserted.
      Determine the proper way to communicate with the visitor's browser regarding element style and color
    */

    // check for a defined element for link testing
    runstate.test_elem = document.getElementById('linktest');
    // create a test container at the bottom of the page no test element exists
    if( !runstate.test_elem ){
      runstate.test_elem = document.createElement('div');
      runstate.test_elem.id = 'linktest';
      runstate.test_elem.style.height = '1px';
      runstate.test_elem.style.width = '1px';
      document.body.appendChild(runstate.test_elem);
    }
    runstate.link = document.createElement('a');
    runstate.link.id = 'test_link';
    runstate.test_elem.appendChild(runstate.link);
    
    // Determine the proper method needed to communicate with the visitor's browser regarding element style and color
    if( runstate.link.currentStyle ) {
      this.islinkvisited=function(url) {
        var link = document.createElement('a');
        link.href = url;
        runstate.test_elem.appendChild(link);
        // does the color of the link match your defined :visited value?
        var color = link.currentStyle.color;
        if( color == '#000000' ) {
          runstate.test_elem.removeChild(link);
          return true;
        }
        else {
          runstate.test_elem.removeChild(link);
          return false;
        }
      };
    }
    else {
      this.islinkvisited=function(url) {
        var link = document.createElement('a');
        link.href = url;runstate.test_elem.appendChild(link);
        // does the color of the link match your defined :visited value expressed in RGB?
        var computed_style = document.defaultView.getComputedStyle(link,null);
        if (computed_style) {
          if( computed_style.color == 'rgb(0, 0, 0)' ) {
            runstate.test_elem.removeChild(link);
            return true;
          }
        }
        else{
          runstate.test_elem.removeChild(link);
          return false;
        }
      };
    }
    return true;
  },
  
  scan:function() {
    /*
      Scan defined links for possible :visited matches
    */
    var links = testlinks.mappers;
    for (var i=0;i<links.length;i++){
      var linktype = links[i];
      if ( linktype.provider && linktype.urlset ) {
        var mapper = linktype.provider;
        console.log('Testing ' + mapper + ', ' + linktype.urlset.length);
        for (var j=0;j<linktype.urlset.length;j++) {
          var url = linktype.urlset[j];
          var found = this.islinkvisited(url);
          if (found) {
            if ( runstate.visitedlinks && runstate.visitedlinks.indexOf(mapper)<0 ){
              console.log(mapper);
              runstate.visitedlinks.push(mapper);
              return; // stop scanning. first one wins
            }
          }
          url=found=null;
        }
        mapper=null;
      }
      linktype=null;
    }
    links=null;
    runstate.test_elem.innerHTML = '';
  },
  
  addmap:function() {
    var map = document.getElementById('map');
    var insert = '';
    if (map) {
	  switch (runstate.visitedlinks[0]) {
        case 'mapquest':
          insert = '<object id="aolmap" type="text/html" data="/code/maps/aol.html" standby="Loading MapQuest map" height="400" width="400"></object>';
          break;
        case 'yahoo':
          insert = '<object id="yahoomap" type="text/html" data="/code/maps/yahoo.html" standby="Loading Yahoo map" height="400" width="400"></object>';
          break;
        case 'openstreetmap':
          insert = '<object id="openstreetmap" type="text/html" data="/code/maps/openmap.html" standby="Loading OpenStreet map" height="400" width="400"></object>';
          break;
        case 'winlive':
          insert = '<object id="winlivemap" type="text/html" data="/code/maps/winlive.html" standby="Loading Windows Live map" height="400" width="400"></object>';
          break;
        default: // google
          insert = '<object id="googlemap" type="text/html" data="/code/maps/google.html" standby="Loading Google map" height="400" width="400"></object>';
          break;
	  }
      map.innerHTML = insert;
    }
  },
  
  run:function() {
    // check if we need to run a test
    if ( !this.alreadyScanned() ) {
      this.init();
      this.scan();
    }
    // only take action if something matches
    if ( this.hasVisitedLinks() ) {
      this.addmap();
    }
  }
};
}();
