% use Mojo::JSON qw( encode_json );
% layout 'yancy';
% content_for head => begin
    %= javascript "/yancy/vue.js"
    %= javascript "/yancy/marked.js"

    %= stylesheet begin
        main {
            position: relative;
            margin-top: 10px;
        }

        .clickable {
            cursor: pointer;
        }
        th.clickable:hover {
            background: #dee2e6;
        }

        .sidebar {
            position: fixed;
            padding: 0;
            left: 0;
            top: 0;
            bottom: 0;
            padding-top: 66px;
            background: #f8f9fa;
            box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);
            overflow: scroll;
            z-index: 10;
        }
        .sidebar .nav-link {
            color: #666;
        }
        .sidebar .nav-link:hover {
            color: #212529;
        }
        .sidebar .nav-link.active {
            color: #007bff;
        }
        .sidebar .sidebar-heading {
            font-size: .75rem;
            text-transform: uppercase;
        }
        .sidebar .sidebar-top {
            display: none;
        }

        .toast-container {
            position: absolute;
            top: 0.4em;
            right: 1em;
            width: 200px;
            z-index: 1000;
        }

        .data-table tbody tr:nth-child( odd ) td,
        .data-table thead th {
            white-space: nowrap;
            max-width: 30em;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        .data-table tbody tr:nth-child( odd ).open + tr td {
            padding-bottom: 0.75em;
        }
        .data-table tbody tr:nth-child( even ) td {
            padding: 0;
            border: 0;
        }
        .data-table textarea, .add-item textarea {
            width: 100%;
        }
        .add-item {
            margin-top: 0.75em;
        }
        .add-field-element {
           display: flex;
        }
        .field-element-button {
            margin-right: 1em;
            width: 2.75em;
            height: 2.75em;
        }
        .yes-no input {
            display: none;
        }
        .yes-no label {
            min-width: 3.25em;
        }

        .markdown-editor-panels {
            width: calc( 100% - 2px );
            height: 50vh;
            border: 1px solid #ccc;
            border-radius: .25em;
        }

        .markdown-editor-panels > div,
        .markdown-editor-panels > textarea {
            display: inline-block;
            width: 49%;
            height: 100%;
            vertical-align: top;
            box-sizing: border-box;
            padding: 0 20px;
            overflow: scroll;
        }

        div.markdown-editor-panels > textarea {
            border: none;
            border-right: 1px solid #ccc;
            resize: none;
            outline: none;
            background-color: #f6f6f6;
            font-size: 14px;
            font-family: 'Monaco', courier, monospace;
            padding: 20px;
        }

        .filters .filter-desc {
            vertical-align: middle;
        }

        /* Fix Bootstrap 4 problem: https://github.com/twbs/bootstrap/issues/23454 */
        .is-invalid + .invalid-feedback {
            display: block;
        }

        @media (min-width: 575.98px) {
            /* Force sidebar to always be open on larger screens */
            #sidebar-collapse.collapse {
                display: block;
            }
        }

        @media (min-width: 992px) {
            .markdown-preview {
                display: none;
            }
            .markdown-editor .collapse {
                display: inline-block;
            }
        }

        @media (max-width: 575.98px) {
            .sidebar {
                position: absolute;
                top: 0;
                left: 0;
                bottom: auto;
                right: 0;
                padding-top: 0;
                z-index: 10;
                box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .1);
            }
            .sidebar-collapse {
                height: 0;
            }
            .sidebar .sidebar-top {
                display: flex;
            }
            main {
                margin-top: 66px;
            }
        }

        @media (max-width: 992px) {
            div.markdown-editor-panels > div,
            div.markdown-editor-panels > textarea {
                display: block;
                width: 100%;
            }
            div.markdown-editor-panels > div.collapse,
            div.markdown-editor-panels > textarea.collapse {
                display: none;
            }
        }

    % end
% end

% for my $include ( @{ app->yancy->editor->include } ) {
    %= include $include
% }

<main id="app" class="container-fluid">

    <div v-if="hasSchema" class="sidebar col-sm-3 col-md-3 col-lg-2">
        <div class="bg-dark p-2 justify-content-between sidebar-top">
            <button class="btn btn-outline-light" type="button"
                data-toggle="collapse" data-target="#sidebar-collapse"
                aria-controls="sidebar-collapse" aria-expanded="false"
                aria-label="<%= l 'Toggle navigation' %>">
                <i class="fa fa-bars"></i> <%= l 'Menu' %>
            </button>
            <a class="btn btn-outline-light" href="<%= stash 'return_to' %>">
                <i class="fa fa-sign-out"></i> <%= l 'Back' %>
            </a>

        </div>

        <div id="sidebar-collapse" class="collapse">
            % my $menu = app->yancy->editor->menu;
            % for my $category ( sort keys %$menu ) {
                % my $menu_items = $menu->{ $category };
                <h6 class="sidebar-heading text-muted px-3 mt-3">
                    <%= $category %>
                </h6>
                <ul class="nav flex-column" data-menu="<%= $category %>">
                    % for my $item ( @$menu_items ) {
                    <% my $link_destination =
                        $item->{component} ? (
                            sprintf '@click.prevent="setComponent( %s )"', qq{'$item->{component}'}
                        )
                        : ''
                        ;
                    %>
                        <li class="nav-item">
                            <a href="#" class="nav-link" data-menu-item="<%= $item->{title} %>"
                                <%== $link_destination %>
                            >
                                %= $item->{title}
                            </a>
                        </li>
                    % }
                </ul>
            % }

            <h6 class="sidebar-heading text-muted px-3 mt-2">
                <%= l 'Schema' %>
            </h6>

            <ul id="sidebar-schema-list" class="nav flex-column">
                <!-- schema list -->
                <li v-for="( val, key ) in schema" class="nav-item">
                    <a href="#" @click.prevent="setSchema( key )"
                        class="nav-link" :data-schema="key"
                        :class="currentSchema == key ? 'active' : ''"
                    >
                        {{ val.operations.list.schema.title || key }}
                    </a>
                </li>
            </ul>

        </div>
    </div>

    <div v-if="hasSchema !== null && !hasSchema" class="alert alert-danger" role="alert">
        <h4 class="alert-heading"><%= l 'No Schema Configured' %></h4>
        <p class="mb-0"><%== l 'No Schema Configured description' %></p>
    </div>

    <div v-show="error && error.fetchSpec" class="alert alert-danger" role="alert">
        <h4 class="alert-heading"><%= l 'Error Fetching API Spec' %></h4>
        <p><%= l 'Error from server:' %> {{ error.fetchSpec }}</p>
        <p class="mb-0"><%= l 'Error Fetching API Spec description' %></p>
    </div>

    <div class="row">
        <div v-show="currentComponent" class="offset-sm-3 col-sm-9 offset-md-3 col-md-9 offset-lg-2 col-lg-10 table-responsive-md">
            <keep-alive><component ref="currentComponent" :is="currentComponent"></component></keep-alive>
        </div>
        <div v-show="currentSchema && !currentComponent" class="offset-sm-3 col-sm-9 offset-md-3 col-md-9 offset-lg-2 col-lg-10 table-responsive-md">
            <!-- current schema -->
            <h2>{{ currentSchema.title ? currentSchema.title : currentSchemaName }}</h2>
            <div v-if="currentSchema.description"
                v-html="marked( currentSchema.description )"></div>

            <div v-show="error && error.fetchPage" class="alert alert-danger" role="alert">
                <h4 class="alert-heading"><%= l 'Error Fetching Data' %></h4>
                <p class="mb-0"><%= l 'Error from server:' %> {{ error.fetchPage }}</p>
            </div>

            <div class="schema-buttons d-flex">
                <button @click="fetchPage()" class="btn btn-primary mr-1"><%= l 'Refresh' %></button>
                <a v-if="currentSchema['x-view-url']" :href="currentSchema['x-view-url']" class="btn btn-secondary mr-1">
                    <i class="fa fa-eye" aria-hidden="true"></i> <%= l 'View' %>
                </a>
                <button @click="newFilter = { }" class="new-filter btn btn-outline-secondary mr-1">
                    <%= l 'Add Filter' %>
                </button>
                <button @click="showAddItem()" id="add-item-btn" class="btn btn-outline-secondary ml-auto"
                    :class="{active:addingItem}"
                >
                    <%= l 'Add Item' %>
                </button>
            </div>

            <div v-if="addingItem" class="add-item">
                <div v-if="error && error.addItem" class="alert alert-danger" role="alert">
                    <h4 class="alert-heading"><%= l 'Error Adding Item' %></h4>
                    <p class="mb-0"><%= l 'Error from server:' %> {{ error.addItem }}</p>
                    <p v-if="error.details">
                        <button class="btn" type="button" data-toggle="collapse" data-target="#add-item-error-details" aria-expanded="false" aria-controls="add-item-error-details">
                            <%= l 'Show Details' %>
                        </button>
                        <div class="collapse" id="add-item-error-details">
                            <div class="card card-body">
                                {{ error.details }}
                            </div>
                        </div>
                    </p>
                </div>
                <item-form id="new-item-form" v-model="newItem"
                    :schema="currentOperations['add'].schema"
                    @close="cancelAddItem" @input="addItem"
                    :error="formError"
                    :show-read-only="false"
                />
            </div>

            <div class="filters mt-1">
                <form id="filter-form" class="form-inline" v-if="newFilter"
                    @submit.prevent="addFilter()"
                >
                    <select class="custom-select col-md-4 col-lg-4" v-model="newFilter.field">
                        <option v-for="col in columns" :value="col.field">
                            {{ col.title }}
                        </option>
                    </select>
                    <input class="form-control col-sm-12 col-md-4 col-lg-5" v-model="newFilter.value">
                    <span class="d-inline-flex justify-space-between col-lg-3 col-md-4" style="padding: 0">
                        <button style="flex: 1 1 50%" class="add-filter btn btn-outline-success"><%= l 'Add' %></button>
                        <button style="flex: 1 1 50%" @click.prevent="cancelFilter()" class="remove-filter btn btn-outline-danger"><%= l 'Remove' %></button>
                    </span>
                </form>
                <div v-for="( filter, i ) in filters">
                    <span class="filter-desc">Filter: <code>{{ filter.field }}</code> matches <code>{{ filter.value }}</code></span>
                    <button class="remove-filter btn btn-outline-danger" @click="removeFilter(i)">Remove</button>
                </div>
            </div>

            <div class="table-responsive">
                <table style="margin-top: 0.5em; width: 100%" class="table data-table" :data-schema="currentSchemaName">
                    <thead class="thead-light">
                        <tr>
                            <th></th>
                            <th v-for="( col, i ) in columns"
                                class="clickable"
                                @click="toggleSort( col )"
                            >
                                <i class="fa" :class="sortClass( col )"></i>
                                {{col.title}}
                            </th>
                        </tr>
                    </thead>
                    <tbody>
                        <template v-for="( row, i ) in items">
                        <tr :data-item-id="rowId( row )" :class="openedRow == i ? 'open' : ''">
                            <td style="width: 5em">
                                <a v-if="currentSchema['x-view-item-url']" :href="rowViewUrl(row)" title="View" class="view-button">
                                    <i class="fa fa-eye" aria-hidden="true"></i>
                                </a>
                                <a href="#" @click.prevent="toggleRow(i)" title="Edit" class="edit-button">
                                    <i class="fa fa-pencil-square-o" aria-hidden="true"></i>
                                </a>
                                <a href="#" @click.prevent="confirmDeleteItem(i)" title="Delete" class="delete-button">
                                    <i class="fa fa-trash-o" aria-hidden="true"></i>
                                </a>
                            </td>
                            <td v-for="col in columns">
                                <span v-if="col.template" v-html="fillTemplate( col.template, row )"></span>
                                <span v-if="col.field && !col.template">{{ renderValue( col.field, row[col.field] ) }}</span>
                            </td>
                        </tr>
                        <tr>
                            <td :colspan="2 + columns.length">
                                <div v-if="openedRow == i" v-show="error && error.saveItem" class="alert alert-danger" role="alert">
                                    <h4 class="alert-heading">Error Saving Item</h4>
                                    <p class="mb-0"><%= l 'Error from server:' %> {{ error.saveItem }}</p>
                                    <p v-if="error.details">
                                        <button class="btn" type="button" data-toggle="collapse" data-target="#edit-item-error-details" aria-expanded="false" aria-controls="edit-item-error-details">
                                            <%= l 'Show Details' %>
                                        </button>
                                        <div class="collapse" id="edit-item-error-details">
                                            <div class="card card-body">
                                                {{ error.details }}
                                            </div>
                                        </div>
                                    </p>
                                </div>
                                <item-form class="edit-form" v-if="openedRow == i" v-model="items[i]"
                                    :schema="currentOperations['set'].schema"
                                    @close="toggleRow(i)" @input="saveItem(i)"
                                    :error="formError"
                                />
                            </td>
                        </tr>
                        </template>
                    </tbody>
                </table>
            </div>

            <p v-if="items.length == 0">
                No items found.
                <a href="#" @click.prevent="showAddItem()">Create an item</a>.
            </p>

            <nav aria-label="List page navigation">
                <ul class="pagination">
                    <li class="page-item" :class="currentPage == 1 ? 'disabled' : ''">
                        <a class="page-link" href="#" aria-label="First"
                            @click.prevent="gotoPage( 1 )"
                        >
                            <span aria-hidden="true">&laquo;</span>
                            <span class="sr-only">First</span>
                        </a>
                    </li>
                    <li class="page-item" :class="currentPage == 1 ? 'disabled' : ''">
                        <a class="page-link" href="#" aria-label="Previous"
                            @click.prevent="gotoPage( currentPage - 1 )"
                        >
                            <span aria-hidden="true">&lsaquo;</span>
                            <span class="sr-only">Previous</span>
                        </a>
                    </li>
                    <li class="page-item disabled" v-if="pagerPages[0] > 1">
                        <span class="page-link">&hellip;</span>
                    </li>
                    <li v-for="page in pagerPages" class="page-item"
                        :class="page == currentPage ? 'active': ''"
                    >
                        <a class="page-link" href="#" @click.prevent="gotoPage( page )">
                            {{ page }}
                        </a>
                    </li>
                    <li class="page-item disabled" v-if="pagerPages[ pagerPages.length - 1 ] < totalPages">
                        <span class="page-link">&hellip;</span>
                    </li>
                    <li class="page-item" :class="currentPage >= totalPages ? 'disabled' : ''">
                        <a class="page-link" href="#" aria-label="Next"
                            @click.prevent="gotoPage( currentPage + 1 )"
                        >
                            <span aria-hidden="true">&rsaquo;</span>
                            <span class="sr-only">Next</span>
                        </a>
                    </li>
                    <li class="page-item" :class="currentPage >= totalPages ? 'disabled' : ''">
                        <a class="page-link" href="#" aria-label="Last"
                            @click.prevent="gotoPage( totalPages )"
                        >
                            <span aria-hidden="true">&raquo;</span>
                            <span class="sr-only">Last</span>
                        </a>
                    </li>
                </ul>
            </nav>
        </div>
    </div>

    <div class="toast-container" aria-live="polite" aria-atomic="true">
        <div v-for="toast in toasts" class="toast show" role="alert" aria-live="assertive" aria-atomic="true">
            <div class="toast-header">
                <i v-if="toast.icon" class="mr-2 fa" :class="toast.icon" aria-hidden="true"></i>
                <strong class="mr-auto">{{ toast.title || "Alert" }}</strong>
                <button @click="removeToast( event, toast )" type="button" class="ml-2 mb-1 close"
                    aria-label="Close"
                >
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div v-if="toast.text" class="toast-body">
                {{ toast.text }}
            </div>
        </div>
    </div>

    <div id="confirmDelete" class="modal" tabindex="-1" role="dialog">
        <div class="modal-dialog" role="document">
            <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">Confirm Delete</h5>
            </div>
        <div class="modal-body">
            <p>Are you sure you want to delete this item?</p>
        </div>
        <div class="modal-footer">
            <button @click.prevent="deleteItem()" type="button" class="btn btn-danger">Delete</button>
            <button @click.prevent="cancelDeleteItem()" type="button" class="btn btn-secondary">Cancel</button>
        </div>
    </div>

</main>

<template id="item-form">
    <div>
        <form @submit.prevent="save()">
            <div class="pull-right" style="margin-bottom: 4px">
                <label class="btn btn-secondary">Show Raw <input type="checkbox" v-model="showRaw" /></label>
            </div>
            <button class="btn btn-primary save-button">Save</button>
            <button type="button" @click="cancel()" class="btn btn-danger cancel-button">Cancel</button>
            <div v-if="!showRaw">
                <div v-for="( conf, i ) in properties" class="form-group" style="clear: both">
                    <label :for="'field-' + conf.name + '-' + _uid">
                        {{ conf.title }} {{ isRequired( conf.name ) ? '*' : '' }}
                    </label>
                    <edit-field v-model="$data._value[conf.name]"
                        :name="conf.name" :example="example[conf.name]" :schema="conf"
                        :required="isRequired( conf.name )" :valid="!error[conf.name]"
                        :aria-labelledby="'field-' + conf.name + '-desc-' + _uid"
                    /></edit-field>
                    <div v-show="error[conf.name]" class="invalid-feedback">Error: {{ error[ conf.name ] }}</div>
                    <small v-if="conf.description" :id="'field-' + conf.name + '-desc-' + _uid"
                        v-html="marked( conf.description )"></small>
                </div>
            </div>
            <div v-if="showRaw && rawError" class="alert alert-danger" role="alert" style="clear: both">
                <h4 class="alert-heading">Error Parsing JSON</h4>
                <p class="mb-0">{{ rawError.message }}</p>
            </div>
            <textarea v-if="showRaw" rows="10" v-model="rawValue" @change="updateRaw"></textarea>
        </form>
    </div>
</template>
<template id="edit-field">
    <div :class="!valid ? 'is-invalid' : ''">
        <input v-if="fieldType != 'select' && fieldType != 'checkbox' && fieldType != 'markdown' && fieldType != 'textarea' && fieldType != 'file' && fieldType != 'array' && fieldType != 'foreign-key'"
            :name="name"
            :type="fieldType" :pattern="pattern" :required="required"
            :inputmode="inputMode"
            :minlength="minlength" :maxlength="maxlength"
            :min="min" :max="max"
            :readonly="readonly"
            :placeholder="example"
            v-model="$data._value" @change="input" class="form-control"
            :class="!valid ? 'is-invalid' : ''"
        />
        <textarea v-if="fieldType == 'textarea'" :required="required"
            :name="name" :disabled="readonly" v-model="$data._value"
            @change="input" :class="!valid ? 'is-invalid' : ''"
            rows="5"></textarea>
        <select v-if="fieldType == 'select'"
            :name="name" :required="required" :disabled="readonly"
            v-model="$data._value" @change="input"
            class="custom-select"
            :class="!valid ? 'is-invalid' : ''"
        >
            <option v-if="!required" :value="undefined">- empty -</option>
            <option v-for="val in schema.enum">{{val}}</option>
        </select>
        <div v-if="fieldType == 'checkbox'"
            class="btn-group yes-no"
        >
            <label class="btn btn-xs" :class="$data._value ? 'btn-success active' : 'btn-outline-success'"
                @click="readonly || ( $data._value = true )"
            >
                <input type="radio" :name="_uid"
                    v-model="$data._value" @change="input" :value="true"
                > Yes
            </label>
            <label class="btn btn-xs" :class="!$data._value ? 'btn-danger active' : 'btn-outline-danger'"
                @click="readonly || ( $data._value = false )"
            >
                <input type="radio" :name="_uid"
                    v-model="$data._value" @change="input" :value="false"
                > No
            </label>
        </div>
        <div v-if="fieldType == 'markdown'" class="markdown-editor">
            <div class="markdown-editor-button-bar mb-1">
                <button type="button" class="btn btn-outline-secondary markdown-preview"
                    :class="{active:showHtml}" @click.prevent="showHtml = !showHtml"
                >
                    Preview
                </button>
            </div>
            <div class="markdown-editor-panels">
                <textarea :name="name" v-model="$data._value" @change="input" :required="required" :disabled="readonly" :class="{collapse:showHtml}"></textarea>
                <div v-html="html" class="markdown-preview" :data-name="name" :class="{collapse:!showHtml}"></div>
            </div>
        </div>
        <div v-if="fieldType == 'array'">
            <ul style="list-style: none;">
                <li v-for="(child, ix) in children" class="add-field-element">
                <button v-on:click="removeChild(ix)" type="button" class="btn btn-sm btn-outline-secondary field-element-button">
                    <i aria-hidden="true" class="fa fa-trash-o" ></i>
                </button>
                <div style="display:inline-block">
                    <edit-field
                        @input="input()"
                        v-model="child.value"
                        :schema="child.schema"
                        :name="child.name" :example="child.example"
                        :required="child.required" :valid="child.valid"
                        :aria-labelledby="'field-' + child.name + '-desc-' + _uid"
                    ></edit-field>
                </div>
                </li>
                <li class="add-field-element">
                <button v-on:click="addChild" type="button" class="btn btn-sm btn-outline-secondary field-element-button">
                    <i aria-hidden="true" class="fa fa-plus" ></i>
                </button>
                </li>
            </ul>
        </div>
        <upload-field v-if="fieldType == 'file'" :disabled="readonly"
            v-model="$data._value" @input="input" :name="name"
            :class="!valid ? 'is-invalid' : ''"
        ></upload-field>
        <foreign-key-field v-if="fieldType == 'foreign-key'" :disabled="readonly"
            v-model="$data._value" @input="input" :name="name"
            :schema-name="$props.schema['x-foreign-key']"
            :display-field="$props.schema['x-display-field']"
            :value-field="$props.schema['x-value-field']"
            :class="!valid ? 'is-invalid' : ''"
        ></foreign-key-field>
    </div>
</template>

<template id="upload-field">
    <div>
        <label class="btn btn-secondary upload-button" :for="_uid">Upload File</label>
        <input type="file" style="display: none;" :name="name" :id="_uid" @change="uploadFile">
        <img v-if="value" :src="value" style="display: block; max-height: 50vh" />
    </div>
</template>

<template id="foreign-key-field">
    <div class="btn-group dropright foreign-key" :data-name="name" :id="uid" :class="loading ? 'loading' : 'loaded'">
        <button type="button" :name="name" class="btn btn-secondary dropdown-toggle"
            aria-haspopup="true" aria-expanded="false"
            data-toggle="dropdown" data-boundary="viewport"
        >
            {{ displayValue }}
        </button>
        <div class="dropdown-menu pt-0" style="max-width: 80vw;">
            <form @submit.prevent="submitSearch">
                <div class="input-group p-1">
                    <input type="text" class="form-control" placeholder="Search" aria-label="Search"
                        v-model="searchQuery"
                    >
                    <div class="input-group-append">
                        <button @click.stop.prevent="submitSearch" class="btn btn-primary" type="button">Search</button>
                    </div>
                </div>
            </form>
            <div class="list-group list-group-flush">
                <button tabindex="0" class="list-group-item list-group-item-action" v-for="item in searchResults" @click.prevent="select(item)">
                    {{ item.display }}
                </button>
            </div>
        </div>
    </div>
</template>

<script>var specUrl = '<%= stash 'api_url' %>';</script>
%= javascript "/yancy/app.js"
%= javascript begin
Yancy.i18n = <%== encode_json {
    'Data validation failed' => l( 'Data validation failed' ),
    'Internal server error' => l( 'Internal server error' ),
} %>;
% end