var Typekit = (function() {

/*
 * A tiny DOM library that's only what Typekit's Javascript requires.
 */
var MiniLib = (function() {

  var defaultView = document.defaultView || {};

  var isReady = false;
  var readyBound = false;
  var readyList = [];

  function ready() {
    if (!isReady) {
      isReady = true;
      for (var i = 0; i < readyList.length; i ++) {
        readyList[i].call(null);
      }
    }
  }

  // DOM ready binding borrowed from jQuery 1.3.2
  function bindReady() {
    if (readyBound) return;
    readyBound = true;

    // Mozilla, Opera and webkit nightlies currently support this event
    if ( document.addEventListener ) {
      // Use the handy event callback
      document.addEventListener("DOMContentLoaded", function() {
        document.removeEventListener("DOMContentLoaded", arguments.callee, false);
        ready();
      }, false );

    // If IE event model is used
    } else if (document.attachEvent) {
      // ensure firing before onload,
      // maybe late but safe also for iframes
      document.attachEvent("onreadystatechange", function() {
        if (document.readyState === "complete") {
          document.detachEvent("onreadystatechange", arguments.callee);
          ready();
        }
      });

      // If IE and not an iframe
      // continually check to see if the document is ready
      if (document.documentElement.doScroll && window == window.top) (function() {
        if (isReady) return;

        try {
          // If IE is used, use the trick by Diego Perini
          // http://javascript.nwbox.com/IEContentLoaded/
          document.documentElement.doScroll("left");
        } catch (error) {
          setTimeout(arguments.callee, 0);
          return;
        }

        // and execute any waiting functions
        ready();
      })();
    }

    // A fallback to window.onload, that will always work
    if (window.onload) {
      var load = window.onload;
      window.onload = function() { load(); ready(); }
    } else {
      window.onload = ready;
    }
  }

  return {
    ready: function(fn) {
      bindReady();
      if (isReady) {
        fn();
      } else {
        readyList.push(fn);
      }
    },
    insertInto: function(tagName, e) {
      var t = document.getElementsByTagName(tagName)[0];
      if (t && t.lastChild) {
        // This is safer than appendChild in IE. appendChild causes random
        // JS errors in IE. Sometimes errors in other JS exectution, sometimes
        // complete "This page cannot be displayed" errors. For our purposes,
        // it's equivalent because we don't need to insert at any specific
        // location.
        t.insertBefore(e, t.lastChild);
        return true;
      } else {
        return false;
      }
    },
    createStyleElement: function(contents) {
      var e = document.createElement('style');
      e.setAttribute('type', 'text/css');
      if (e.styleSheet) { // IE
        e.styleSheet.cssText = contents;
      } else {
        e.appendChild(document.createTextNode(contents))
      }
      return e;
    },
    createCssLink: function(src) {
      var e = document.createElement('link');
      e.setAttribute('rel', 'stylesheet');
      e.setAttribute('type', 'text/css');
      e.setAttribute('href', src);
      return e;
    },
    css: function(e, prop) {
      if (defaultView.getComputedStyle) {
        var cs = defaultView.getComputedStyle(e, null);
        return cs ? cs.getPropertyValue(prop) : null;
      } else if (e.currentStyle) {
        return e.currentStyle[prop];
      }
    },
    loadScript: function(src, fn) {
      var head = document.getElementsByTagName("head")[0];
      if (head) {
        var script = document.createElement("script");
        script.src = src;
        var done = false;
        script.onload = script.onreadystatechange = function() {
          if (!done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')) {
            done = true;
            if (fn) fn();
            script.onload = script.onreadystatechange = null;
            // Avoid a bizarre issue with unclosed <base> tag in IE6 - http://blog.dotsmart.net/2008/04/
            if (script.parentNode.tagName == 'HEAD') head.removeChild(script);
          }
        };
        head.appendChild(script);
      }
    }
  }
})();
var BrowserBehavior = {
  ua: function(user_agent_string) {
    if (user_agent_string) {
      for (var i = 0; i < this.matchers.length; i++) {
        var matcher = this.matchers[i][1];
        if (matcher.call(null, user_agent_string)) {
          var format = this.matchers[i][0];
          return { 'fonts': (!!format), 'format': format };
        }
      }
      return { 'fonts': false };
    }
  },
  matchers: [],
  add: function(format, matcher) {
    this.matchers.push([format, matcher]);
  }
};

// Firefox
BrowserBehavior.add('standards', function(ua) {
  var match = ua.match(/rv:(\d+\.\d+)\.(\d+).*Gecko\//)
  if (ua.match(/rv:1.9.1b[123]{1}/)) return false;
  if (match) {
    var version = match[1]+match[2];
    return parseFloat(version) >= 1.91;
  }
});

// Safari
BrowserBehavior.add('standards', function(ua) {
  if (ua.match(/iPhone/)) return false;

  var match;
  if (ua.match(/Chrome/)){
    match = ua.match(/Chrome\/(\d+\.\d+)\.(\d+)\.(\d+)/)
    if (match) {
      var major = parseFloat(match[1]);
      var minor = parseInt(match[2]);
      var minorminor = parseInt(match[3]);

      if (major > 4){
        return true;
      }else if (major == 4 && minor > 249){
        return true;
      }else if (major == 4 && minor == 249 && minorminor >= 4){
        return true;
      }else{
        return false;
      }
    }
  }

  match = ua.match(/Safari\/(\d+\.\d+)/)
  if (match) {
    var version = match[1];
    return parseFloat(version) >= 525.13;
  }
});

// Internet Explorer
BrowserBehavior.add('explorer', function(ua) {
  var match = ua.match(/MSIE\s(\d+\.\d+)/);
  if (match) {
    var version = match[1];
    return parseFloat(version) >= 6.0;
  }
});

var badgeFactories = {};
var options = {};
var dataSets = {};
var callbacks = {};
var statsData = {};
var kitsLoaded = [];

if (window.tkKitsTracked == undefined) window.tkKitsTracked = 0;

// Override the configuration
function setOptions(opts) {
  for (var k in opts) {
    options[k] = opts[k];
  }

  // Log after setting options so if we set just changed it will reflect that.
  log('setOptions', options);

  var ua = options['ua'];
  if (ua) {
    // Always set fonts and compatibility from the given UA so that they can't
    // be overridden at will.
    var browser = BrowserBehavior.ua(ua);
    options.fonts = browser.fonts;
    options.compatibility = browser.format;

    log('setOptions:fonts', options.fonts, options.compatibility);
  }
}


// Utilities ------------------------------------------------------------------

// Always use log(..) to write to the console. It will automatically disable.
// when logging shouldn't be used.
function log(msgs) {
  if (options.debug && window.console && window.console.log) {
    window.console.log(arguments);
  }
}

// Add a callback function to for the kit to the given set of callbacks.
function addCallback(kitId, callback) {
  if (!callbacks[kitId]) callbacks[kitId] = [];
  if (callback) {
    callbacks[kitId].push(callback);
    log('addCallback', kitId, callbacks[kitId].length, callback);
  }
}

// Add a callback that populates the stats for the given kitId.
function addStatsCallback(kitId) {
  var startTime = new Date().getTime();
  addCallback(kitId, function(data) {
    getKitStats(kitId).time = (new Date().getTime()) - startTime;
  })
}

// Execute all of the given callbacks for the kit.
function executeCallbacks(kitId, data) {
  log('executeCallbacks', kitId);
  var list = callbacks[kitId];
  if (list) {
    for (var i = 0; i < list.length; i++) {
      list[i](data);
    }
  }
}


// Kits -----------------------------------------------------------------------

function addDataSet(kitId, securityToken, badgeOptions, data) {
  log('addDataSet', kitId, securityToken, badgeOptions, data);
  dataSets[kitId] = {
    'kitId': kitId,
    'securityToken': securityToken,
    'badgeOptions': badgeOptions,
    'callbackData': data
  };
  dataSets[kitId].callbackData.kitId = kitId;
}

function loadEverything(kitId, compatibility, opts) {
  if (kitId) {
    log('loading kit', kitId);
    loadKit(dataSets[kitId], compatibility, opts);
  } else {
    for (var id in dataSets) {
    log('loading kit', id);
      loadKit(dataSets[id], compatibility, opts);
    }
  }
}

function waitForBody(fn) {
  var interval = setInterval(function() {
    if (document.getElementsByTagName('body')[0]) {
      fn();
      clearInterval(interval);
    }
  }, 50);
}

function loadKit(dataSet, compatibility, opts) {
  if (dataSet && dataSet.kitId) {
    log('loadKit', dataSet);
    kitsLoaded.push(dataSet);
    writeKitStyle(dataSet.callbackData);
    if (opts['beforeLoad']) {
      opts['beforeLoad'](dataSet.callbackData);
    }
    if (options.fonts) {
      addStatsCallback(dataSet.kitId);
      addCallback(dataSet.kitId, function() {
        if (opts['afterLoad']) {
          opts['afterLoad'](dataSet.callbackData);
        }
      });
      if (navigator.userAgent.match(/MSIE/)) {
        waitForBody(function() {
          loadKitStyle(dataSet.kitId, dataSet.securityToken, compatibility);
        });
      } else {
        loadKitStyle(dataSet.kitId, dataSet.securityToken, compatibility);
      }
    } else {
      if (opts['noFonts']) {
        opts['noFonts'](dataSet.callbackData);
      }
    }
  } else {
    log('loadKit', 'data is invalid', dataSet);
  }
}

// Write CSS into the document using the kit's data.
function writeKitStyle(data) {
  if (data && data.fonts) {
    var fonts = data.fonts;
    var css = [];
    for (var i = 0; i < fonts.length; i++) {
      var font = fonts[i];
      if (font) {
        var cssStack = fonts[i].css_stack;
        var selectors = fonts[i].css_selectors;
        if (cssStack && selectors) {
          for (var j = 0; j < selectors.length; j++) {
            css.push(selectors[j] + '{font-family:' + cssStack + ';}');
          }
        }
      }
    }
    MiniLib.insertInto('head', MiniLib.createStyleElement(css.join('')));
  }
}

// Injects a <link> element pointing to our stylesheet.
function loadKitStyle(kitId, securityToken, compatibility) {
  var url = options.scheme + options.host + options.root + '/k/' + kitId + '-' + compatibility + '.css?' + securityToken;
  log('loadKitStyle', url);
  if (MiniLib.insertInto('head', MiniLib.createCssLink(url))) {
    waitForStyleLoaded(kitId);
  }
}

// Implements a loading event for CSS
function waitForStyleLoaded(kitId) {
  log('waitForStyleLoaded', kitId);

  // Create the element that will capture the fonts loaded state.
  var loadHook = document.createElement('div');
  loadHook.setAttribute('id', 'tkload' + kitId);
  loadHook.setAttribute('style', 'display:none');

  var hooked = false;
  function checkStyleLoaded() {
    if (hooked) {
      var color = MiniLib.css(loadHook, 'color');
      if (color == 'rgb(255, 0, 0)' || color == 'red') {
        if (dataSets[kitId]) {
          executeCallbacks(kitId, dataSets[kitId].callbackData);
          return;
        }
      }
    } else {
      hooked = MiniLib.insertInto('body', loadHook);
    }
    setTimeout(checkStyleLoaded, options.styleLoadIntervalTime);
  }
  checkStyleLoaded();
}

function getKitStats(kitId) {
  var stats = statsData[kitId];
  if (!stats) {
    stats = statsData[kitId] = { time: 0 };
  }
  return stats;
}


// Run ------------------------------------------------------------------------

// Set default configuration options.
setOptions({
  scheme: 'http://',
  host: 'use.typekit.com',
  root: '',
  assetHost: 'use.typekit.com',
  assetRoot: '',
  colophonHost: 'typekit.com',
  ua: navigator.userAgent,
  styleLoadIntervalTime: 20,
  debug: false
});

// Return the Typekit private interface.
function privateInterface() {
  return {
    'addDataSet': addDataSet,
    'clearDataSets': function() { dataSets = {}; }
  };
}

// Return the Typekit public interface.
function publicInterface() {
  return {
    'configure': setOptions,
    'load': function(__args__) {
      var kitId, opts;
      if (typeof arguments[0] == "string") {
        kitId = arguments[0];
        opts = arguments[1];
      } else {
        kitId = null;
        opts = arguments[0];
      }
      loadEverything(kitId, options.compatibility, opts || {});
    },
    'stats': getKitStats
  };
}

addDataSet("iub8ino","3bb2a6e53c9684ffdc9a98f6195b2a62600ffda1783020e14daccfc868b6573dd8aca49a39f2c08d2b65c67105ef2fd505f4b1d0717bfa907181f57bea9fe0b7a8d5660d6196b93ccff02baa6411186ee219bb59ddf966f3a5c9ab615a1fbe3ae43d50086e0c6cbec48f0032ff0ff751020a177ebe1e60316f362a1467a5ab6b5af1167bfdaed3cbf634656e9cd509d70e66f2e5d1549fb045a34b450ebfb8b0ded05ac3ff689b5dd69391c1c99b75686c57c702886897086118c911b3622407e7658e4b1bddbd25bba374",{enabled:false},{fonts:[{css_stack:'"ff-dax-compact-web-pro-1","ff-dax-compact-web-pro-2",sans-serif',css_selectors:[".tk-ff-dax-compact-web-pro"]}]});

return publicInterface();
})();
