/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* Custom JavaScript code in the MarkDown docs */

// Enable language-specific code tabs
// similar to spark code tabs, except can have spaces and periods
function codeTabs() {
    var counter = 0;
    var langImages = {
      "scala": "img/scala-sm.png",
      "python": "img/python-sm.png",
      "java": "img/java-sm.png"
    };
    $("div.codetabs").each(function() {
      $(this).addClass("tab-content");
  
      // Insert the tab bar
      var tabBar = $('<ul class="nav nav-tabs" data-tabs="tabs"></ul>');
      $(this).before(tabBar);
  
      // Add each code sample to the tab bar:
      var codeSamples = $(this).children("div");
      codeSamples.each(function() {
        $(this).addClass("tab-pane");
        var lang = $(this).data("lang");
        var image = $(this).data("image");
        var notabs = $(this).data("notabs");
        var capitalizedLang = lang.substr(0, 1).toUpperCase() + lang.substr(1);
        
        // for flexibility, allow spaces and periods
        var langConv = lang.replace(/\./g, "_");
        langConv = langConv.replace(/ /g, "_");
        
        var id = "tab_" + langConv + "_" + counter;
        $(this).attr("id", id);
        if (image != null && langImages[lang]) {
          var buttonLabel = "<img src='" +langImages[lang] + "' alt='" + capitalizedLang + "' />";
        } else if (notabs == null) {
          var buttonLabel = "<b>" + capitalizedLang + "</b>";
        } else {
          var buttonLabel = ""
        }
        tabBar.append(
          '<li><a class="tab_' + langConv + '" href="#' + id + '">' + buttonLabel + '</a></li>'
        );
      });
  
      codeSamples.first().addClass("active");
      tabBar.children("li").first().addClass("active");
      counter++;
    });
    $("ul.nav-tabs a").click(function (e) {
      // Toggling a tab should switch all tabs corresponding to the same language
      // while retaining the scroll position
      e.preventDefault();
      var scrollOffset = $(this).offset().top - $(document).scrollTop();
      $("." + $(this).attr('class')).tab('show');
      $(document).scrollTop($(this).offset().top - scrollOffset);
    });
  }
  
  // Code tabs that don't switch all tabs
  //
  // Note that codeTabs2() should be called after codeTabs(). If codeTabs2()
  // were called first, 2 click events would get attached to the tabs since
  // "ul.nav-tabs a" and "ul.nav-tabs2 a" would both apply. Note that 
  // nav-tabs and nav-tabs2 are both used because css doesn't support
  // inheritance, and nav-tabs has a significant amount of styling in
  // bootstrap.css.
  function codeTabs2() {
    var counter = 0;
    var langImages = {
      "scala": "img/scala-sm.png",
      "python": "img/python-sm.png",
      "java": "img/java-sm.png"
    };
    $("div.codetabs2").each(function() {
      $(this).addClass("tab-content");
  
      // Insert the tab bar
      var tabBar = $('<ul class="nav nav-tabs nav-tabs2" data-tabs="tabs"></ul>');
      $(this).before(tabBar);
  
      // Add each code sample to the tab bar:
      var codeSamples = $(this).children("div");
      codeSamples.each(function() {
        $(this).addClass("tab-pane");
        var lang = $(this).data("lang");
        var image = $(this).data("image");
        var notabs = $(this).data("notabs");
        
        // for flexibility, allow spaces and periods
        var langConv = lang.replace(/\./g, "_");
        langConv = langConv.replace(/ /g, "_");
        
        var id = "tab_" + langConv + "_" + counter;
        $(this).attr("id", id);
        if (image != null && langImages[lang]) {
          var buttonLabel = "<img src='" +langImages[lang] + "' alt='" + lang + "' />";
        } else if (notabs == null) {
            var buttonLabel = "<b>" + lang + "</b>";
        } else {
          var buttonLabel = ""
        }
        tabBar.append(
            '<li><a class="tab_' + langConv + '" href="#' + id + '">' + buttonLabel + '</a></li>'
        );
      });
  
      codeSamples.first().addClass("active");
      tabBar.children("li").first().addClass("active");
      counter++;
    });
    $("ul.nav-tabs2 a").click(function (e) {
      e.preventDefault();
      var scrollOffset = $(this).offset().top - $(document).scrollTop();
      $(this).tab('show'); // only switch current tab - makes comparisons feel slightly better on this page
      $(document).scrollTop($(this).offset().top - scrollOffset);
    });
  }
  
  
  // A script to fix internal hash links because we have an overlapping top bar.
  // Based on https://github.com/twitter/bootstrap/issues/193#issuecomment-2281510
  function maybeScrollToHash() {
    if (window.location.hash && $(window.location.hash).length) {
      var newTop = $(window.location.hash).offset().top - 57;
      $(window).scrollTop(newTop);
    }
  }
  
  $(function() {
    codeTabs();
    codeTabs2();
    // Display anchor links when hovering over headers. For documentation of the
    // configuration options, see the AnchorJS documentation.
    anchors.options = {
      placement: 'left'
    };
    anchors.add();
  
    $(window).bind('hashchange', function() {
      maybeScrollToHash();
    });
  
    // Scroll now too in case we had opened the page on a hash, but wait a bit because some browsers
    // will try to do *their* initial scroll after running the onReady handler.
    $(window).load(function() { setTimeout(function() { maybeScrollToHash(); }, 25); }); 
  });
  