(function (window) {
  
  var old_seatgeek = window.seatgeek,
      api_base = window.SG_API_BASE || "http://api.seatgeek.com",
      static_base = window.SG_STATIC_BASE || "http://static.seatgeek.com";
  
  // miniajax, from: http://code.google.com/p/miniajax/
  function $(e){if(typeof e=='string')e=document.getElementById(e);return e};
  function collect(a,f){var n=[];for(var i=0;i<a.length;i++){var v=f(a[i]);if(v!=null)n.push(v)}return n};
  var ajax={};
  ajax.x=function(){try{return new ActiveXObject('Msxml2.XMLHTTP')}catch(e){try{return new ActiveXObject('Microsoft.XMLHTTP')}catch(e){return new XMLHttpRequest()}}};
  ajax.serialize=function(f){var g=function(n){return f.getElementsByTagName(n)};var nv=function(e){if(e.name)return encodeURIComponent(e.name)+'='+encodeURIComponent(e.value);else return ''};var i=collect(g('input'),function(i){if((i.type!='radio'&&i.type!='checkbox')||i.checked)return nv(i)});var s=collect(g('select'),nv);var t=collect(g('textarea'),nv);return i.concat(s).concat(t).join('&');};
  ajax.send=function(u,f,m,a){var x=ajax.x();x.open(m,u,true);x.onreadystatechange=function(){if(x.readyState==4)f(x.responseText)};if(m=='POST')x.setRequestHeader('Content-type','application/x-www-form-urlencoded');x.send(a)};
  ajax.get=function(url,func){ajax.send(url,func,'GET')};
  ajax.gets=function(url){var x=ajax.x();x.open('GET',url,false);x.send(null);return x.responseText};
  ajax.post=function(url,func,args){ajax.send(url,func,'POST',args)};
  ajax.update=function(url,elm){var e=$(elm);var f=function(r){e.innerHTML=r};ajax.get(url,f)};
  ajax.submit=function(url,elm,frm){var e=$(elm);var f=function(r){e.innerHTML=r};ajax.post(url,f,ajax.serialize(frm))};
  
  ajax.jsonp=function(url,f) {
    setTimeout(function () {
      var head = document.getElementsByTagName("head")[0],
          script = document.createElement('script'),
          cb = "sg_callback_" + Math.floor(Math.random()*10000),
          src = /\?/.test(url) ? url + "&callback=" + cb : url + "?callback=" + cb;
      
      window[cb] = function (param) {
        try {
            delete window[cb];
        } catch(e) {}
        f(param);
      };
      script.type = 'text/javascript';
      script.src = src;
      head.appendChild(script);
    }, 0);
  };
  
  // Search within a node for elements with a class matching searchClass
  function getElementsByClass(node, searchClass, tag) {
    var matches = [],
        node = node || document,
        tag = tag || "*",
        els = node.getElementsByTagName(tag),
        pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
        
    var i, len = els.length;
    for (i = 0; i < len; i++) {
      if (pattern.test(els[i].className))
        matches.push(els[i]);
    }
    return matches;
  }
  
  function getClassNames(elem) {return elem.className.split(/\s+/)};
  
  function contains(a, obj){
    for(var i = 0; i < a.length; i++)
      if(a[i] === obj)
        return true;
    
    return false;
  }
  
  function serialize (obj) {
    var str = [];
    for(var p in obj)
       str.push(p + "=" + encodeURIComponent(obj[p]));
    return str.join("&");
  }
  
  function parse_params(widget) {
    return collect(getClassNames(widget), function (i) {
      var ms = i.match(/^sg_widget_(.+)$/i);
      return (ms && ms.length > 0) ? RegExp["$+"] : null;
    });
  }
  
  function html (lines) {return lines.join("\n");}
  
  function structure_html (orientation, aid) {
    var homepage = "http://seatgeek.com/" + (aid ? "?aid=" + aid : "");
    if (orientation == "horizontal")
      return html([
        '<div class="sgWidgetWrapperH">',
            '<div class="jwFrameHeader">',
                '<div class="jwFrameHeaderR">',
                    '<div class="jwFrameHeaderC">',
                        '<div class="jwTitle">',
                            '<a target="_blank" class="jwHeaderLink" href="' + homepage + '">',
                                'SeatGeek | Loading...',
                            '</a>',
                        '</div>',
                    '</div>',
                '</div>',
            '</div>',
            '<div class="jwFrameContentL">',
                '<div class="jwFrameContent">',
                    '<div class="jwCaptions">',
                        '<img src="' + static_base + '/widget/images/h/title_h.gif" width="30" height="157" alt="title">',
                    '</div>',
                    '<div class="jwFrame1"></div>',
                    '<div class="jwFrame2"></div>',
                '</div>',
            '</div>',
            '<div class="jwFF">',
                '<div class="jwFFR">',
                    '<div class="jwFFC">',
                        '<div class="jwFFLogo">',
                            '<div class="footerText">',
                                'get <a href="' + homepage + '" target="_blank">sold out tickets</a>',
                            '</div>',
                            '<a class="logoLink" href="' + homepage + '" target="_blank">',
                                '<img src="' + static_base + '/widget/images/logo_seatgeek.gif" width="79" height="26" alt="" />',
                            '</a>',
                        '</div>',
                    '</div>',
                '</div>',
            '</div>',
        '</div>'
      ]);
    else
      return html([
        '<div class="jWW">',
            '<div class="jwFH">',
                '<div class="jwFHR">',
                    '<div class="jwFHC">',
                        '<a href="' + homepage + '" class="jwT">',
                            'SeatGeek | Loading...',
                        '</a>',
                    '</div>',
                '</div>',
            '</div>',
            '<div class="jwFCL"></div>',
            '<div class="jwFF">',
                '<div class="jwFFR">',
                    '<div class="jwFFC">',
                        '<div class="jwFFLogo">',
                            '<div class="footerText">',
                                'get <a href="' + homepage + '" target="_blank">sold out tickets</a>',
                            '</div>',
                            '<a class="logoLink" href="' + homepage + '" target="_blank">',
                                '<img src="' + static_base + '/widget/images/logo_seatgeek.gif" width="79" height="26" alt="" />',
                            '</a>',
                        '</div>',
                    '</div>',
                '</div>',
            '</div>',
        '</div>'
      ]);
  }
  
  function forecast_html (forecast) {
    if (forecast <= 6) {
      return [
        "Forecast unavailable",
        "Prices forecasted to <span class=\"sg_forecast_1\">fall</span>",
        "Prices forecasted to <span class=\"sg_forecast_2\">fall</span>",
        "Prices forecasted to <span class=\"sg_forecast_3\">hold</span>",
        "Prices forecasted to <span class=\"sg_forecast_4\">rise</span>",
        "Prices forecasted to <span class=\"sg_forecast_5\">rise</span>"
      ][forecast];
    }
    return "";
  }
  
  function prediction_html (forecast, price) {
    return html([
      '<div class="sg_forecast sg_forecast_' + forecast + '">',
        '<div class="sg_arrow">' + (forecast == 0 && price > 0 ? 'Tickets from' : '') + '</div>',
        price > 0 ? '$' + Math.ceil(price) : '',
      '</div>'
    ]);
  }

  function details_html (title, url, venue, datetime) {
    return html([
      '<a href="' + url + '" target="_blank" class="jwLinkB">' + title + '</a><br />',
      venue + '<br />',
      datetime
    ]);
  }
  
  // given a widget wrapper, build it out
  function buildWidget(widget, type, args) {
    
    /*
    var example_args = {
      orientation: "vertical",
      slug:        "new-york-mets",
      limit:       3
    }
    */
    
    var args = args || {},
        orientation = args.orientation || "vertical",
        type = type || "in_your_area",
        version = 1,
        namespace = "events",
        query = {limit: args.limit || 3};
    
    switch (type) {
      case "in_your_area":
        query.category = args.category || "all";
        break;
      
      case "upcoming_for_teamband":
        if (args.id) query.id = args.id;
        else if (args.slug) query.slug = args.slug;
        else if (args.myspace_slug) query.myspace_slug = args.myspace_slug;
        else throw "\"upcoming_for_teamband\" sg_widget requires an argument of one of either id, slug, or myspace_slug"
        break;
      
      default:
        throw "Unknown sg_widget type: \"" + type + "\"";
    }
    
    // affiliate id (optional)
    if (typeof SG_AFFILIATE_ID !== 'undefined')
      query.aid = SG_AFFILIATE_ID;
    
    var path = "/"+version+"/"+namespace+"/"+type+".json?"+serialize(query);
    
    (function (response) {
      var headID = document.getElementsByTagName("head")[0],
          cssNode = document.createElement('link'),
          css_url = "/widget/css/combined.css";
      
      cssNode.type = 'text/css';
      cssNode.rel = 'stylesheet';
      cssNode.href = static_base + css_url;
      cssNode.media = 'screen';
      headID.appendChild(cssNode);
      
      widget.innerHTML = structure_html(orientation, query.aid);
      
      ajax.jsonp(api_base + path, function (json) {
        var title = type === "upcoming_for_teamband" ? json.name + " Tickets" : json.name;
        ({
          horizontal: function () {
            var k = getElementsByClass(widget, 'jwHeaderLink')[0],
                o = getElementsByClass(widget, 'jwFrameContent')[0],
                s = '<div class="jwCaptions"><img src="http://static.seatgeek.com/widget/images/h/title_h.gif" width="30" height="157" alt="title"></div>',
                events = json.events.slice(0,2);
            
            k.innerHTML = title;
            k.setAttribute("href", json.url);
            
            if (events.length <= 0) {
              var for_text = type === "upcoming_for_teamband" ? "for this team/artist" : "in your area";
              s += html([
                '<div>',
                  '<div class="jwFLC">',
                    '<div style="width:200px !important; margin:50px auto !important; text-align:center !important;">',
                      'Sorry, we currently have no upcoming events ' + for_text + ', ',
                      '<br><a href="http://seatgeek.com/" class="jwLinkB">find more tickets here</a>.',
                    '</div>',
                  '</div>',
                '</div>'
              ]);
            } else {
              for (i = 0; i < events.length; i++) {
                var e = events[i];
                var eck = e.title;
                if (orientation === 'horizontal' && eck.length > 36) {
                  eck = eck.substring(0, 30);
                  eck = eck.replace(/\w+$/, '');
                }
              
                s+='<div class="jwFrame'+(i+1)+'"><div class="jwFrameListC"><a href="'+e.url+'" class="jwLinkB">'+eck+'</a> <br />'+e.venue_name+'<br />'+e.date+', '+e.time+'</div><div class="sg_forecast_'+e.numeric_forecast+'"><div class="jwFrameArrow"><img src="http://static.seatgeek.com/widget/images/h/spacer.gif" alt="" />$'+Math.ceil(e.lowest_price)+'</div></div><div class="jwFrameListF">';
                s += forecast_html(e.numeric_forecast);
                s += '</div></div>';
              }
            }
            
            o.innerHTML = s;
          },
          vertical: function () {
            var k = getElementsByClass(widget, 'jwT')[0],
                o = getElementsByClass(widget, 'jwFCL')[0],
                s ='<div class="jwFC"><div class="jwFL">',
                events = json.events,
                i = 0;
            
            k.innerHTML = title;
            k.setAttribute("href", json.url);
            
            if (events.length <= 0) {
              var for_text = type === "upcoming_for_teamband" ? "for this team/artist" : "in your area";
              s += html([
                '<div>',
                  '<div class="jwFLC">',
                    '<div style="padding-top:5px !important;text-align:center !important;">',
                      'Sorry, we currently have no upcoming events ' + for_text + ', ',
                      '<br><a href="http://seatgeek.com/" class="jwLinkB">find more tickets here</a>.',
                    '</div>',
                  '</div>',
                '</div>'
              ]);
            } else {
              s += html(collect(events, function (e) {
                return html([
                  '<div class="new-vertical' + ((i++ % 2==0) ? '' : ' odd') + '">',
                    '<div class="jwFLC">',                      '<div class="wtf">',
                        '<a href="' + e.url + '" class="button"><img src="' + static_base + '/widget/images/find-tickets-orange.png" /></a>',
                        '<a href="' + e.url + '" target="_blank" class="jwLinkB">' + e.short_title + '</a><br />',
                      '</div>',
                      '<div class="details">',
                        e.time + ', ' + e.date + ' at ' + e.venue_name,
                      '</div>',
                    '</div>',,
                    '<div class="jwFLF sg_forecast_' + e.numeric_forecast + '">',
                      '<span class="sg_arrow"></span>',
                      forecast_html(e.numeric_forecast),
                    '</div>',
                  '</div>'
                ]);
              }));
            }
            
            s+='</div></div>';
            o.innerHTML=s;
          }
        }[orientation])();
        
        if (typeof args.onLoad == "function") args.onLoad.call(args, widget, json);
      });
    })();
  }
  
  // export our api to the window namespace
  window.seatgeek = window.seatgeek || {
    widget: function (widget, type, args) {
      var elem = typeof widget == "string" ? document.getElementById(widget) : widget;
      if (elem) buildWidget(elem, type, args);
    }
  };
  
  // build widgets in all of the .sg_widget elements in the page
  seatgeek._widgets = seatgeek._widgets || [];
  collect(getElementsByClass(document, "sg_widget", "div"), function (widget) {
    if (contains(seatgeek._widgets, widget)) return false; // sg_widget has already been built
    seatgeek._widgets.push(widget);
    
    var params = parse_params(widget),
        orientation = "vertical",
        type = null,
        limit = 3,
        args = {};
  
    // widget orientation (defaults to vertical)
    if (contains(params, "horizontal"))
      args.orientation = "horizontal";
  
    // type of widget (required)
    if (contains(params, "in_your_area")) {
      type = "in_your_area";
      var category = widget.getAttribute("for");
      if (category) args.category = category;
    } else if (contains(params, "upcoming_for_teamband")) {
      type = "upcoming_for_teamband";
      var id = widget.getAttribute("for");
      if (parseInt(id, 10) == id)
        args.id = id;
      else
        args.slug = id;
    }
  
    buildWidget(widget, type, args);
  });
})(window);
