<!DOCTYPE html>
<!--
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.
-->
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
    <link rel="stylesheet" href="items.css" type="text/css" media="screen"/>
    <title>Brooklyn Objects</title>
  </head>

  <body>
    <div id="container">
      <div id="header">
        <div id="identity">
          <a href="https://brooklyn.incubator.apache.org/" rel="home">Brooklyn</a>
        </div>
      </div>

      <ul class="nav nav-tabs">
        <li class="active"><a href="#entities" data-toggle="tab">Entities</a></li>
        <li><a href="#policies" data-toggle="tab">Policies</a></li>
        <li><a href="#enrichers" data-toggle="tab">Enrichers</a></li>
      </ul>

      <div class="tab-content">
        <div class="tab-pane active" id="entities">
          <input class="filter form-control" type="text" placeholder="Filter by type, e.g. webapp or nosql">
        </div>
        <div class="tab-pane" id="policies">
          <input class="filter form-control" type="text" placeholder="Filter by type, e.g. ha">
        </div>
        <div class="tab-pane" id="enrichers">
          <input class="filter form-control" type="text" placeholder="Filter by type, e.g. http">
        </div>
        <div class="tab-pane" id="locations"></div>
        <div class="tab-pane" id="locationResolvers"></div>
      </div>
    </div>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js" type="text/javascript"></script>
    <script src="../../style/js/underscore-min.js" type="text/javascript"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
    <script src="libs/js/bloodhound.js" type="text/javascript"></script>
    <script src="common.js" type="text/javascript"></script>
    <script src="items.js" type="text/javascript"></script>
    <script type="text/javascript">
        if (!String.prototype.trim) {
            String.prototype.trim = function () {
                return this.replace(/^\s+|\s+$/g, '');
            };
        }
        var card = function (collection, cardFunction, target) {
            var cards = _.map(collection, cardFunction);
            $(target).append(cards.join(""));
        };
        var ESCAPE_KEY = 27;

        var filter = function (element) {
            var $element = $(element),
                $tab = $element.parent(),
                kind = $tab.attr("id"),
                collection = items[kind];
            if (!collection) {
                console.warn("Unable to determine type for input", element);
                return;
            }

            // Number.MAX_VALUE configures Bloodhound to return all matches.
            var bloodhound = new Bloodhound({
                name: kind,
                local: collection,
                limit: Number.MAX_VALUE,
                datumTokenizer: function (d) {
                    return Bloodhound.tokenizers.nonword(d.type);
                },
                queryTokenizer: Bloodhound.tokenizers.nonword
            });
            bloodhound.initialize();

            // Filter items as input changes
            var allAnchors = $tab.find("a").map(function (index, a) { return $(a); });
            var hideAnchorsNotMatchingQuery = function () {
                var query = $element.val();
                query = query.trim();
                if (!query) {
                    $tab.find("a").removeClass("hide");
                } else {
                    var matchedTypes = {};
                    bloodhound.get(query, function (suggestions) {
                        _.each(suggestions, function (s) {
                            // approximate a set!
                            matchedTypes[s.type] = true;
                        });
                    });
                    _.each(allAnchors, function (a) {
                        if (_.has(matchedTypes, a.data("type"))) {
                            a.removeClass("hide");
                        } else {
                            a.addClass("hide");
                        }
                    });
                }
            };
            $element.on("input", hideAnchorsNotMatchingQuery);
            // In case page is loaded with text in input, e.g. from back button.
            hideAnchorsNotMatchingQuery();

            $element.on("keydown", function (e) {
                if (e.keyCode == ESCAPE_KEY) {
                    $element.val("");
                    hideAnchorsNotMatchingQuery();
                }
            });
        };

        $(document).ready(function () {
            card(items.entities, brooklyn.entityCard, "#entities");
            card(items.policies, brooklyn.policyCard, "#policies");
            card(items.enrichers, brooklyn.enricherCard, "#enrichers");
            //transformItemAndAddToElement(items.locations, brooklyn.locationCard, "#locations");
            //items.locationResolvers.forEach(function (element) { $("#locationResolvers").append("<tr><td>" + element + "</td></tr>"); });
            $("input.filter").each(function (index, element) {
                filter(element);
            });
        });
    </script>
  </body>
</html>
