
/**
 * WoSnake: Search and save keywords from Google, Yahoo
 * Usage:
 *   WoSnake.q(keyphrase[, callback]);
 *      keyphrase - keyphrase (only english letters and figures)
 *      callback  - callback-function with two parameters: keywords(array), failure(integer)
 * 
 *           \
 *            \    /^\/^\                                               
 *               _|__|  O|                                              
 *    \/        /~     \_/ \                                             
 *     \_______|__________/  \                                           
 *              \_______      \                                         
 *                      `\     \                 \                      
 *                        |     |                  \                    
 *                       /      /                    \                  
 *                      /     /                       \\                
 *                    /      /                         \ \              
 *                   /     /                            \  \            
 *                 /     /             _----_            \   \          
 *                /     /           _-~      ~-_         |   |          
 *               (      (        _-~    _--_    ~-_     _/   |          
 *                \      ~-____-~    _-~    ~-_    ~-_-~    /           
 *                  ~-_           _-~          ~-_       _-~ 
 *                     ~--______-~                ~-___-~             
 */

var WoSnake = {
    
    alphabet: 'etaoinshrdlcumwfgypbvkjxqz ',
    
    request: function(letter, combination){
        if (typeof combination == 'undefined') combination = 0;
        else if (WoSnake.gap.indexOf(combination.toString()) != -1) return false;
        var query = WoSnake.word.join(' ');
        switch (combination){
            case 0:
                query += ' ' + letter;
                break;
            case 1:
                if (WoSnake.word.length > 1)
                    query = query.replace('  ', (' ' + letter + ' ')) + '&cp=' + (WoSnake.word[0].length + 2);
                else return false;
                break;
            case 2:
                query = letter + ' ' + query + '&cp=1';
                break;
        }
        return query.replace(/\s+/g, '%20');
    },
    
    insert: function(word, level){
        WoSnake.words[level].push(word);
    },
    
    timer: function(name){
        if (typeof name == 'undefined'){
            for (var name in WoSnake.timers){
                if (WoSnake.timers[name])
                    clearTimeout(WoSnake.timers[name]);
            }
        }
        else{
            if (typeof WoSnake.timers[name] != 'undefined' && WoSnake.timers[name])
                clearTimeout(WoSnake.timers[name]);
            WoSnake.timers[name] = setTimeout(function(){
                WoSnake.failure++;
                WoSnake.ready();
            }, 15000);
        }
        return true;
    },
    
    ready: function(){
        if ((++WoSnake.status) == 2 && WoSnake.timer()){
            var keywords = [];
            var unique  = function(value, set){ for (var i = 0; i < set.length; i++){ if (value == set[i]) return false; } return true; };
            var words = WoSnake.words;
            var reg = /^[-_a-zA-Z0-9\s.]+$/;
            for (var i = 0; i < words.length; i++){
                words[i].sort();
                for (var j = 0; j < words[i].length; j++){
                    if (reg.test(words[i][j]) && unique(words[i][j], keywords))
                        keywords.push(words[i][j]);
                }
            }
            WoSnake.onready(keywords, WoSnake.failure);
        }
    },
    
    init: function(word, callback){
        if (typeof WoSnake.word == 'undefined'){
            // google
            if (!window.google) window.google = {};
            if (!window.google.ac) window.google.ac = {};
            window.google.ac.h = function(data){
                if (data.length && data.length == 2){
                    for (var i = 0; i < data[1].length; i++)
                        WoSnake.insert(data[1][i][0], i);
                    var offset = WoSnake.alphabet.length*3 - WoSnake.pointers[0];
                    if (offset < 4 && data[1].length < 10)
                        WoSnake.gap += 3-offset;
                }
                WoSnake.go('google');
            };
            // yahoo
            window.yasearch = function(data){
                if (data.r){
                    for (var i = 0; i < data.r.length; i++)
                        WoSnake.insert(data.r[i][0], i);
                }
                if (WoSnake.pointers[1]+1 == WoSnake.alphabet.length && data.r.length < 10)
                    WoSnake.pointers[1] = 0;
                WoSnake.go('yahoo');
            };
            WoSnake.timers = {};
        }
        WoSnake.pointers = [WoSnake.alphabet.length*3, WoSnake.alphabet.length];
        WoSnake.onready = (typeof callback == 'undefined') ? function(keywords, failure){} : callback;
        WoSnake.status = WoSnake.failure = 0;
        WoSnake.words = [];
        WoSnake.word = word;
        WoSnake.gap = '';
        for (var i = 0; i < 25; i++)
            WoSnake.words[i] = [];
        return WoSnake;
    },
    
    go: function(from){
        // google
        if (from.indexOf('google') >= 0){
            if (WoSnake.pointers[0]){
                WoSnake.pointers[0]--;
                WoSnake.timer('google');
                var q = WoSnake.request(WoSnake.alphabet.charAt(parseInt(WoSnake.pointers[0]/3)), WoSnake.pointers[0]%3);
                if (q) jQuery.getScript('http://www.google.com/complete/search?hl=en&q=' + q);
                else WoSnake.go('google');
            } else WoSnake.ready();
        }
        // yahoo
        if (from.indexOf('yahoo') >= 0){
            if (WoSnake.pointers[1]){
                WoSnake.pointers[1]--;
                WoSnake.timer('yahoo');
                jQuery.getScript('http://sugg.search.yahoo.com/gossip-us-fp/?nresults=10&queryfirst=2&output=yjsonp&version=&command=' + WoSnake.request(WoSnake.alphabet.charAt(WoSnake.pointers[1])));
            } else WoSnake.ready();
        }
    },
    
    q: function(word, callback){
        if (word){
            word = ('' + word).replace(/(^\s+|\s+$)/g, '').replace(/\s+/g, ' ').split(' ');
            if (word.length > 1) word.splice(1, 0, '');
            WoSnake.init(word, callback).go('google|yahoo');
        }
    }
        
};
