/*
  Code from "Developing Featherweight Web Services with JavaScript"
      http://feather.elektrum.org/
  (c)An Elektrum Press, retain this notice
      License: http://feather.elektrum.org/appendix/licenses.html
*/

var arg = new Args ();
var q = new Query ();
var titleKey = Keywords(document.title);
var queryKey = Keywords(q.query);
var keyword = queryKey || arg.keyword || titleKey;
var override = ( arg.override == 1 ) ? 1 : 0;
if ( override && arg.keyword ) keyword = arg.keyword;

var errors = new Array ();

var assoc = ( coinFlip(50) && arg.assoc && arg.assoc.match(/^[-\w]+$/) ) ?
               arg.assoc : 'feather-20';

var Ads = new Object({ '120x150':[6,130,160] ,'120x240':[8,130,250]
                      ,'180x150':[9,190,160] ,'468x60':[13,478,70]
                      ,'120x450':[10,130,460] ,'120x600':[11,130,610]
                      ,'160x600':[14,170,610] ,'text':true });

var Stores = new Object({ "apparel":"Apparel"
                         ,"baby":"Baby"
                         ,"beauty":"Beauty"
                         ,"books":"Books"
                         ,"photo":"Photo"
                         ,"wireless-phones":"Wireless-phones"
                         ,"videogames":"Videogames"
                         ,"pc-hardware":"PC-hardware"
                         ,"dvd":"DVD"
                         ,"electronics":"Electronics"
                         ,"gourmet":"Gourmet"
                         ,"hpc":"Health and Personal Care"
                         ,"garden":"Home and Garden"
                         ,"jewelry":"Jewelry"
                         ,"kitchen":"Kitchen"
                         ,"magazines":"Magazines"
                         ,"music":"Music"
                         ,"mi":"Musical Instruments"
                         ,"software":"Software"
                         ,"sporting":"Sporting"
                         ,"tools":"Tools"
                         ,"toys":"Toys"
                         ,"vhs":"VHS"
                         });


var ad_size;
if ( isSupported( Ads, arg.size ) ) {
  ad_size = arg.size;
}
else
{
  var adSizes = new Array();
  for ( var ad in Ads ) adSizes.push( ad );
  var whatsWrong = arg.size ? 'incorrect' : 'missing';
  errors.push('"size" value is ' + whatsWrong + '; valid sizes are: ' +
              adSizes.join(", ") + '.'
              );
}

if ( arg.keyword && ( arg.keyword.length > 35 ) ) {
  errors.push('"keyword" length is unreasonable (must be 35 chars or less).');
}

var mode;
if ( arg.store && isSupported( Stores, arg.store ) ) {
  mode = arg.store;
}
else if ( arg.store )
{
  var stores = new Array();
  for ( var store in Stores ) stores.push( store );
  errors.push('"store" value is incorrect; valid stores are: '  +
              stores.join(", ") + '.'
              );
}
else
{
  mode = 'books';
}

if ( errors.length > 0 ) {
  showErrors( errors );
} else if ( ad_size == 'text' ) {
  writeAdText( keyword, assoc, mode );
}
else
{
  writeAdBox( keyword, assoc, ad_size, mode );
}

if ( arg.debug ) {
  document.write('<pre>');
  document.writeln('   store: ' + mode);
  document.writeln('    size: ' + ad_size);
  document.writeln(' keyword: ' + keyword);
  document.writeln('   assoc: ' + assoc);
  document.write('override: ' + override);
  document.write('</pre>');
}

// Service logic ends, functions and classes begin

// ARGS object ------------------------------------------------------
// constructor ------------------------
function Args () {
  var scripts = document.getElementsByTagName('script');
  var index = scripts.length - 1;
  var myScript = scripts[index];
  var qString = myScript.src.replace(/^[^?]+\??/,'');
  var params = parseQuery( qString );
  if ( qString ) {
     var params = parseQuery( qString );
     for ( var i in params ) {
        this[i] = params[i][0];
     }
  }
}

// QUERY object ------------------------------------------------------
// constructor ------------------------
function Query () {
  var qString = document.referrer.replace(/^[^\?]+\??/,'') || document.location.href.replace(/^[^\?]+\??/,'')
  if ( qString ) {
     this.queryString = qString;
     this.params = parseQuery( qString );
  }
  if ( this.params ) {
    this.query = chooseBest( this.params )
  }
}

// -----------------------------------
function chooseBest ( params ) {
   var max = 0;
   var choice;
   for ( var i in params ) {
      if ( params[i][1] > max ) {
         choice = params[i][0];
         max = params[i][1];
      }
   }
   return choice;
}

// -----------------------------------
function parseQuery ( query ) {  
   var Params = new Object ();
   if ( ! query ) return Params;
   var Pairs = query.split(/[;&]/)
   var Params = new Object ();
   for ( var i = 0; i < Pairs.length; i++ ) {
      var KeyVal = Pairs[i].split('=')
      if ( ! KeyVal.length == 2 ) continue
      if ( ! ( KeyVal[0] || KeyVal[1] ) ) continue
      var key = unescape( KeyVal[0] )
      var val = unescape( KeyVal[1] )

      val = val.replace(/\+/g, ' ')
      val = val.replace(/&/g, '&amp;');
      val = val.replace(/>/g, '&gt;');
      val = val.replace(/</g, '&lt;')

      var weight = Params[key] ? Params[key][1] : 0

      var wordlikes = val.match( /(\w[-'\w]+\w )|(\w[-'\w]+\w)$/g )

      weight += wordlikes ? wordlikes.length : 0
      if ( key.match(/^(search\w*|(q(uery|w)?\w*)|as_e?p?q|kw?|p(age)?)\b/) ) weight += 2
      if ( key.match(/query/i) ) weight++
      if ( key.match(/\./) ) weight--
      var badChars = val.match(/[^-a-z'" ]/ig)
      weight -= badChars ? badChars.length : 0

      if ( Params[key] && Params[key][0] ) {
          Params[key][0] += ' ' + val
          val = Params[key][0]
      }
     Params[key] = [ val, weight ]
   }
   return Params
}


// Keyword chooser ---------------------------------------------------
//  ------------------------
//  ------------------------
function Keywords ( string, count ) {
   if ( ! string ) return '';
   count = count ? Number(count) : 2;
   var Words = string.split(/["\s]+/);
   var Params = new Object ();
   var Weights = new Array ();
   for ( var i = 0; i < Words.length; i++ ) {
      var word = Words[i];
      // naive pseudo-stemming
      word = word.replace(/\s+$/,'');
      word = word.replace(/ies$/,'y');
      word = word.replace(/sses$/,'ss');
      if ( word.match(/[^s]s$/) ) word = word.replace(/s$/, '');
      var weight = word.length - 2;
      var badChars = word.match(/[^a-z]/ig)
      weight -= badChars ? badChars.length : 0
      Params[word] = weight;
      Weights.push(weight);
   }

   Weights = Weights.sort( numericReverse );
   var cutoff = Weights.length > 2 ? Weights[1] : 1;

   var keywords = new Array ();
   for ( var i = 0; i < Words.length; i++ ) {
      var word = Words[i];
      var weight = Params[word];
      if ( weight >= cutoff ) keywords.push( word );
      if ( keywords.length == count ) break;
   }
   return keywords.join(' ');
}


function numericReverse (a,b) {
  return b - a;
}

// AD TEXT writer ----------------------------------------------------
//  ------------------------
function writeAdText ( keyWords, assocId, Mode ) {
  if ( ! keyWords ) return false;
  var key   = escape( keyWords );
  var mode  = Mode ? escape( Mode ) : 'books';
  var assoc = assocId ? escape( assocId ) : feather-20;

  // some text store modes differ from box ads
  if ( mode.match(/(^apparel|beauty|sporting|gourmet|jewelry|hpc|mi)$/) ) {
    mode += '-index';
  }

  document.write('<a href="http://www.amazon.com/exec/obidos/' +
    'external-search?search-type=ss&amp;tag=' + assoc +
    '&amp;keyword=' + key + '&amp;index=' + mode +
    '">Search for <i>' + unescape(key) + '</i></a> at ' +
    '<a href="http://www.amazon.com/exec/obidos/redirect-home/' +
    assoc + '">Amazon.com</a>.');
}


// AD BOX writer -----------------------------------------------------
//  ------------------------
function writeAdBox ( keyWords, assocId, Ad, Mode ) {
  var key   = escape( keyWords );
  var ad    = Ad ? escape( Ad ) : '120x150';
  var mode  = Mode ? escape( Mode ) : 'books';
  var assoc = assocId ? escape( assocId ) : feather-20;

  var type   = Ads[ad][0];
  var width  = Ads[ad][1];
  var height = Ads[ad][2];

  var iFrame = '<iframe marginwidth="0" marginheight="0" ' +
               'src="http://rcm.amazon.com/e/cm?t=' + assoc + 
               '&o=1&p=' + type + 
               '&l=st1&mode=' + mode +
               '&search=' + key +
               '&=1&fc1=&lc1=&lt1=&bg1=&f=ifr" ' +
               'width="' + width + '" height="' + height +
               '" border="0" frameborder="0" ' +
               'style="border:none;" scrolling="no"></iframe>';

  document.write(iFrame);
}

function coinFlip ( weight ) {
  var w = weight ? Number( weight ) : 1;
  return Math.floor( Math.random() * ( w + 1 ) );
}

function isSupported ( Obj, item ) {
  if ( ! ( Obj && item ) ) return false;
  for ( var i in Obj ) {
    if ( i === item ) return true;
  }
  return false;
}

function showErrors ( err ) {
  document.write('<div style="border:1px solid #000;background-color:#fff;' +
                 'color:#c00;font-size:small;padding:1ex;">' +
                 '<b>WiskerBiscuit service error</b>: ' +
                 err.join(" ") + '<br /><br />See ' +
                 '<a style="color:#03a;font-style:italic" ' +
                 'href="http://feather.elektrum.org/book/whisker-biscuit.html">' +
                 'Developing Featherweight Web Services with JavaScript</a> for service instructions.' +
                 '</div>'
                 );
}

/* (c)2005, Ashley Pond V.
   This is not free code. All rights are reserved. This code may only be
   used in ways consistent with this notice. This code may not be
   copied or altered without written permission.

   See http://feather.elektrum.org/book/whisker-biscuit.html
   for help and more about this service and more license information.
*/

