{#-
       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.
-#}

{#
Each macro is wrapped with an 'if' clause so that a custom theme may extend this file and override individual macros
http://stackoverflow.com/questions/26582731/redefining-imported-jinja-macros
#}


{# account_links are used in primary nav, and off-canvas menu for small screens #}
{% if not account_links %}
{%- macro account_links(c, h, config, login_url, logout_url) %}
    {% if c.user._id %}
        <a href="/auth/preferences/">Account</a>
        <a href="{{c.user.url()}}">{{name}}</a>
        <a href="{{logout_url}}">Log Out</a>
    {% else %}
        {% if h.asbool(config.get('auth.allow_user_registration', True)) %}
            <a href="/auth/create_account">Register</a>
        {% endif %}
        <a href="{{login_url}}">Log In</a>
    {% endif %}
{%- endmacro %}
{% endif %}

{%  if not header %}
{%- macro header(login_url, logout_url) %}
{% set breakpoint='medium' %}
<div class="row">
    <header class="columns small-12 title-bar">
        <div class="title-bar-left">
            {% if g.nav_logo %}
                <a href="{{ g.nav_logo['redirect_link'] }}"><img style="{% if g.nav_logo['image_width'] %}width: {{g.nav_logo['image_width']}}px;{% endif %} {% if g.nav_logo['image_height'] %}height: {{ g.nav_logo['image_height'] }}px;{% endif %}" src="{{ g.nav_logo['image_path'] }}" /></a>
            {% endif %}
            {% for nav_link in g.global_nav %}
                <a href="{{ nav_link['url'] }}" {% if g.nav_logo or not loop.first %}class="show-for-{{ breakpoint }}"{% endif %}>{{ nav_link['title'] }}</a>
            {% endfor %}
        </div>
        <div class="title-bar-right show-for-{{ breakpoint }}">
            {{ account_links(c, h, config, login_url, logout_url) }}
        </div>
        <button class="menu-icon hide-for-{{ breakpoint }}" type="button" data-open="offCanvas"></button>
    </header>
</div>
{%- endmacro %}
{% endif %}


{% if not all_content_wrapper %}
{% macro all_content_wrapper(login_url, logout_url) -%}
    <div class="off-canvas position-right" id="offCanvas" data-off-canvas>
        <div class="menu vertical">
        {% for nav_link in g.global_nav %}
            <a href="{{ nav_link['url'] }}">{{ nav_link['title'] }}</a>
        {% endfor %}
        {{ account_links(c, h, config, login_url, logout_url) }}
        </div>
    </div>
    <div class="off-canvas-content" data-off-canvas-content>
        {{- caller(**kwargs) -}}
    </div>
{%- endmacro %}
{% endif %}


{% if not footer %}
{%- macro footer(year, path_to_static='') %}
<footer id="site-footer" class="row align-right">
    <p>This project is powered by <a href="https://allura.apache.org/">Apache Allura</a>&trade;.</p>
</footer>
{%- endmacro %}
{% endif %}

{% if not custom_js %}
{%- macro custom_js(path_to_static) %}
<script>
    $(document).foundation();
</script>
{%- endmacro %}
{% endif %}

{% if not custom_tracking_js %}
{%- macro custom_tracking_js(accounts, user, project) %}
    {# This should be overridden in your custom theme (e.g., sftheme) to implement custom tracking code. #}
    var _gaq = _gaq || [];

    function _add_tracking(prefix, tracking_id) {
        _gaq.push(
            [prefix+'._setAccount', tracking_id],
            [prefix+'._trackPageview']
        );
    }

    {%- for account in accounts %}
    _add_tracking('acct{{ loop.index }}', '{{account}}');
    {%- endfor %}
    {% if project and project.neighborhood.features['google_analytics'] -%}
      {% if project.neighborhood.tracking_id -%}
          _add_tracking('nbhd', '{{project.neighborhood.tracking_id}}');
      {%- endif %}
      {% if project.tracking_id -%}
          _add_tracking('proj', '{{project.tracking_id}}');
      {%- endif %}
    {%- endif %}

    (function() {
        var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
        ga.src = ('https:' === document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
    })();
{%- endmacro %}
{% endif %}

{% if not extra_header %}
{%- macro extra_header(path_to_static) %}

{%- endmacro %}
{% endif %}

{% if not breadcrumbs %}
{%- macro breadcrumbs(project, app) %}
    <nav aria-label="You are here:" role="navigation" class="row">
        <ul class="breadcrumbs">
            <li><a href="/">Home</a></li>
            {% for label,url in project.breadcrumbs() %}
                {% if not loop.last or app %}
                    <li><a href="{{ url }}">{{ label }}</a></li>
                {% else %}
                    <li>{{ label }}</li>
                {% endif %}
            {% endfor %}
            {% if app %}
                <li>{{ app.config.options.mount_label }}</li>
            {% endif %}
        </ul>
    </nav>
{%- endmacro %}
{% endif %}


{% if not project_header_right %}
{%- macro project_header_right(project, app) %}
  {% if project.neighborhood.icon %}
  <div class="column shrink neighborhood_block">
    <a href="{{project.neighborhood.url()}}"><img {{ lib.project_icon_srcs(project.neighborhood.neighborhood_project) }} class="neighborhood_icon"
       alt="Return to {{project.neighborhood.name}}" title="Return to {{project.neighborhood.name}}"></a>
       <div class="neighborhood_title">
         <h3><a href="{{project.neighborhood.url()}}">{{project.neighborhood.name}}</a></h3>
         {% if project.neighborhood.project_list_url %}
           <div class="neighborhood_title_link">
           <a href="{{project.neighborhood.project_list_url}}">
             View More Projects
           </a>
           </div>
         {% endif %}
    </div>
  </div>
  {% endif %}
{%- endmacro %}
{% endif %}

{% if not login_overlay %}
{%- macro login_overlay() %}
    {% do g.register_js('js/jquery.lightbox_me.js') %}
    {% do g.register_forge_js('js/jquery-ui.min.js') %}
    {% do g.register_js('js/login_overlay.js') %}
    <div id="login_overlay" class="ui-widget-content">
        <h2 class="dark title">Login Required</h2>
        <iframe src="{{g.login_fragment_url}}"></iframe>
    </div>
{%- endmacro %}
{% endif %}

{% if not site_notification %}
{%- macro site_notification() %}
    {% set note = g.theme.get_site_notification() %}
    {% if note %}
        <div id="site-notification">
            <section class="callout primary" data-notification-id="{{note._id}}">
                {{note.content|safe}}
                <button class="close-button btn-close" aria-label="Dismiss alert" type="button">
                  {#  .btn-close instead of data-close, since allura-base.js handles closing it, not Foundation #}
                  <span aria-hidden="true">&times;</span>
                </button>
            </section>
        </div>
    {% endif %}
{%- endmacro %}
{% endif %}

{% if not placeholder_project_icon %}
{%- macro placeholder_project_icon() %}
    <div class="placeholder-icon"></div>
{%- endmacro %}
{% endif %}
