(function() {
  'use strict';

  if (!String.prototype.startsWith) {
    Object.defineProperty(String.prototype, 'startsWith', {
      value: function(search, rawPos) {
        var pos = rawPos > 0 ? rawPos|0 : 0;
        return this.substring(pos, pos + search.length) === search;
      }
    });
  }

  // Parses versions in URL segments like:
  // "3", "dev", "release/2.7" or "3.6rc2"
  var version_regexs = [
    '(?:\\d)',
    '(?:\\d\\.\\d[\\w\\d\\.]*)',
    '(?:dev)',
    '(?:release/\\d.\\d[\\x\\d\\.]*)'];

  var all_versions = {"3.10": "dev (3.10)", "3.9": "3.9", "3.8": "3.8", "3.7": "3.7", "3.6": "3.6", "3.5": "3.5", "2.7": "2.7"};
  var all_languages = {"en": "English", "es": "Spanish", "fr": "French", "ja": "Japanese", "ko": "Korean", "pt-br": "Brazilian Portuguese", "zh-cn": "Simplified Chinese", "zh-tw": "Traditional Chinese"};

  function quote_attr(str) {
      return '"' + str.replace('"', '\\"') + '"';
  }

  function build_version_select(release) {
    var buf = ['<select>'];
    var major_minor = release.split(".").slice(0, 2).join(".");

    $.each(all_versions, function(version, title) {
      if (version == major_minor)
        buf.push('<option value=' + quote_attr(version) + ' selected="selected">' + release + '</option>');
      else
        buf.push('<option value=' + quote_attr(version) + '>' + title + '</option>');
    });

    buf.push('</select>');
    return buf.join('');
  }

  function build_language_select(current_language) {
    var buf = ['<select>'];

    $.each(all_languages, function(language, title) {
      if (language == current_language)
        buf.push('<option value="' + language + '" selected="selected">' +
                 all_languages[current_language] + '</option>');
      else
        buf.push('<option value="' + language + '">' + title + '</option>');
    });
    if (!(current_language in all_languages)) {
        // In case we're browsing a language that is not yet in all_languages.
        buf.push('<option value="' + current_language + '" selected="selected">' +
                 current_language + '</option>');
        all_languages[current_language] = current_language;
    }
    buf.push('</select>');
    return buf.join('');
  }

  function navigate_to_first_existing(urls) {
    // Navigate to the first existing URL in urls.
    var url = urls.shift();
    if (urls.length == 0 || url.startsWith("file:///")) {
      window.location.href = url;
      return;
    }
    $.ajax({
      url: url,
      success: function() {
        window.location.href = url;
      },
      error: function() {
        navigate_to_first_existing(urls);
      }
    });
  }

  function on_version_switch() {
    var selected_version = $(this).children('option:selected').attr('value') + '/';
    var url = window.location.href;
    var current_language = language_segment_from_url();
    var current_version = version_segment_from_url();
    var new_url = url.replace('/' + current_language + current_version,
                              '/' + current_language + selected_version);
    if (new_url != url) {
      navigate_to_first_existing([
        new_url,
        url.replace('/' + current_language + current_version,
                    '/' + selected_version),
        '/' + current_language + selected_version,
        '/' + selected_version,
        '/'
      ]);
    }
  }

  function on_language_switch() {
    var selected_language = $(this).children('option:selected').attr('value') + '/';
    var url = window.location.href;
    var current_language = language_segment_from_url();
    var current_version = version_segment_from_url();
    if (selected_language == 'en/') // Special 'default' case for english.
      selected_language = '';
    var new_url = url.replace('/' + current_language + current_version,
                              '/' + selected_language + current_version);
    if (new_url != url) {
      navigate_to_first_existing([
        new_url,
        '/'
      ]);
    }
  }

  // Returns the path segment of the language as a string, like 'fr/'
  // or '' if not found.
  function language_segment_from_url() {
    var path = window.location.pathname;
    var language_regexp = '/((?:' + Object.keys(all_languages).join("|") + ')/)'
    var match = path.match(language_regexp);
    if (match !== null)
      return match[1];
    return '';
  }

  // Returns the path segment of the version as a string, like '3.6/'
  // or '' if not found.
  function version_segment_from_url() {
    var path = window.location.pathname;
    var language_segment = language_segment_from_url();
    var version_segment = '(?:(?:' + version_regexs.join('|') + ')/)';
    var version_regexp = language_segment + '(' + version_segment + ')';
    var match = path.match(version_regexp);
    if (match !== null)
      return match[1];
    return ''
  }

  function create_placeholders_if_missing() {
    var version_segment = version_segment_from_url();
    var language_segment = language_segment_from_url();
    var index = "/" + language_segment + version_segment;

    if ($('.version_switcher_placeholder').length)
      return;

    var html = '<span class="language_switcher_placeholder"></span> \
<span class="version_switcher_placeholder"></span> \
<a href="/" id="indexlink">Documentation</a> &#187;';

    var probable_places = [
      "body>div.related>ul>li:not(.right):contains('Documentation'):first",
      "body>div.related>ul>li:not(.right):contains('documentation'):first",
    ];

    for (var i = 0; i < probable_places.length; i++) {
      var probable_place = $(probable_places[i]);
      if (probable_place.length == 1) {
        probable_place.html(html);
        document.getElementById('indexlink').href = index;
        return;
      }
    }
  }

  $(document).ready(function() {
    var language_segment = language_segment_from_url();
    var current_language = language_segment.replace(/\/+$/g, '') || 'en';
    var version_select = build_version_select(DOCUMENTATION_OPTIONS.VERSION);

    create_placeholders_if_missing();
    $('.version_switcher_placeholder').html(version_select);
    $('.version_switcher_placeholder select').bind('change', on_version_switch);

    var language_select = build_language_select(current_language);

    $('.language_switcher_placeholder').html(language_select);
    $('.language_switcher_placeholder select').bind('change', on_language_switch);
  });
})();
