<!--
 ~ Copyright 2022 youngmonkeys.org
 ~ 
 ~ Licensed under the ezyplatform, Version 1.0.0 (the "License");
 ~ you may not use this file except in compliance with the License.
 ~ You may obtain a copy of the License at
 ~ 
 ~     https://youngmonkeys.org/licenses/ezyplatform-1.0.0.txt
 ~ 
 ~ 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.
-->

<!DOCTYPE html>
<html
        xmlns="http://www.w3.org/1999/xhtml"
        xmlns:th="http://www.thymeleaf.org"
        xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
        layout:decorate="~{ezyadmin}">

<body>
<div layout:fragment="content" class="row">
    <div class="col-lg-6 col-md-4"></div>
    <div class="col-lg-3 col-md-4 page-search">
        <label for="settingSearchDataType" class="white-space-nowrap d-md-block d-none">
            [[#{type}]]:
        </label>
        <select class="form-control form-select" id="settingSearchDataType"
                onchange="ezyadmin.onSettingStatusSelected();">
            <option value="">[[#{all}]]</option>
            <option th:each="dataType : ${dataTypes}"
                    th:value="${dataType}"
                    th:selected="${dataType == settingSearchDataType}">
                [[#{${dataType.toString().toLowerCase()}}]]
            </option>
        </select>
    </div>
    <div class="col-lg-3 col-md-4 page-search">
        <label for="settingSearchKeyword" class="white-space-nowrap d-md-block d-none">
            [[#{search}]]:
        </label>
        <input type="search" class="form-control" th:value="${settingSearchKeyword}"
               th:placeholder="#{keyword}" id="settingSearchKeyword"
               oninput="ezyadmin.onKeydownToSearchSetting();"
               onkeydown="ezyadmin.onKeydownToSearchSetting();">
    </div>
    <div class="col-12">
        <div class="card">
            <div class="card-body table-responsive p-0">
                <table id="settingListTable" class="table table-bordered table-hover align-middle-cells">
                    <thead>
                    <tr>
                        <th>#</th>
                        <th>[[#{name}]]</th>
                        <th>[[#{value}]]</th>
                        <th class="text-center">[[#{type}]]</th>
                        <th class="text-center">[[#{updated_at}]]</th>
                    </tr>
                    </thead>
                    <tbody id="settingListBody">
                    </tbody>
                </table>
            </div>
            <!-- /.card-body -->
            <div class="card-footer clearfix">
                <span>
                    <span id="settingCountText">0</span>
                    [[${#strings.toLowerCase(#messages.msg('of'))}]]
                    <span id="totalSettingText">0</span>
                    [[${#strings.toLowerCase(#messages.msg('settings'))}]]
                </span>
                <ul class="pagination pagination-sm m-0 float-right">
                    <li class="page-item">
                        <a class="page-link cursor-pointer" id="firstPageButton">
                            <i class="fas fa-arrow-circle-left pl-1 pr-1"></i>
                        </a>
                    </li>
                    <li class="page-item">
                        <a class="page-link cursor-pointer" id="prevPageButton">[[#{prev}]]</a>
                    </li>
                    <li class="page-item">
                        <a class="page-link cursor-pointer" id="nextPageButton">[[#{next}]]</a>
                    </li>
                    <li class="page-item">
                        <a class="page-link cursor-pointer" id="lastPageButton">
                            <i class="fas fa-arrow-circle-right pl-1 pr-1"></i>
                        </a>
                    </li>
                </ul>
            </div>
            <!-- /.card-footer -->
        </div>
    </div>
</div>
<th:block layout:fragment="modals">
<div class="modal fade pt-4rem" id="add-setting">
    <div class="modal-dialog modal-md">
        <div class="modal-content">
            <div class="modal-header">
                <h4 class="modal-title">[[#{add_new_setting}]]</h4>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <form id="addSettingForm" onsubmit="return false;">
                    <div class="form-group row">
                        <label for="addSettingName" class="col-2 col-form-label">[[#{name}]]:</label>
                        <div class="col-10">
                            <label class="col-form-label text-danger d-none" id="addSettingNameErrorLabel" for="addSettingName">
                                <i class="far fa-times-circle"></i> <span id="addSettingNameError"></span>
                            </label>
                            <input type="text" name="name" id="addSettingName"
                                   class="form-control" th:placeholder="#{name}"
                                   onkeydown="ezyadmin.onKeyDownToSaveSetting('add')">
                        </div>
                    </div>
                    <div class="form-group row">
                        <label for="addSettingDataType" class="col-2 col-form-label">
                            [[#{type}]]:
                        </label>
                        <div class="col-10">
                            <label class="col-form-label text-danger d-none" id="addSettingDataTypeErrorLabel" for="addSettingDataType">
                                <i class="far fa-times-circle"></i> <span id="addSettingDataTypeError"></span>
                            </label>
                            <select name="dataType" id="addSettingDataType" class="form-control" aria-label="Type Select"
                                    onchange="ezyadmin.onSettingValueTypeChanged(this, 'add');">
                                <option value="" selected>[[#{select_a_type}]]</option>
                                <option th:each="dataType : ${dataTypes}"
                                        th:value="${dataType}">
                                    [[#{${dataType.toLowerCase()}}]]
                                </option>
                            </select>
                        </div>
                    </div>
                    <div class="form-group row mb-0">
                        <label for="addSettingValue" class="col-2 col-form-label">[[#{value}]]:</label>
                        <div class="col-10">
                            <label class="col-form-label text-danger d-none" id="addSettingValueErrorLabel" for="addSettingValue">
                                <i class="far fa-times-circle"></i> <span id="addSettingValueError"></span>
                            </label>
                            <textarea name="value" id="addSettingValue"
                                      class="form-control" th:placeholder="#{value}" rows="3"></textarea>
                            <div class="input-group cursor-pointer d-none" id="addSettingImageGroup" onclick="ezyadmin.selectSettingMedia('add', 'image');">
                                <input type="text" name="settingImage"
                                       id="addSettingImage" class="form-control" th:placeholder="#{select_an_image}">
                                <div class="input-group-append">
                                    <div class="input-group-text">
                                        <span>[[#{browse}]]</span>
                                    </div>
                                </div>
                            </div>
                            <div class="input-group cursor-pointer d-none" id="addSettingMediaGroup" onclick="ezyadmin.selectSettingMedia('add', 'media');">
                                <input type="text" name="settingMedia"
                                       id="addSettingMedia" class="form-control" th:placeholder="#{select_a_media}">
                                <div class="input-group-append">
                                    <div class="input-group-text">
                                        <span>[[#{browse}]]</span>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="form-group row mt-2">
                        <label for="addChangeLastUpdateTime" class="col-2 col-form-label">
                            [[#{include}]]:
                        </label>
                        <div class="col-10 d-flex align-items-center">
                            <input type="checkbox" name="changeLastUpdateTime" id="addChangeLastUpdateTime" class="form-check wh-1rem">
                            <span class="ml-1">[[#{last_update_time_of_this_setting}]]</span>
                        </div>
                    </div>
                </form>
            </div>
            <div class="modal-footer justify-content-between">
                <div>
                    <button type="button" class="btn btn-default" data-dismiss="modal"
                            onclick="ezyadmin.resetAddSettingModel();">[[#{cancel}]]</button>
                    <button type="button" class="btn btn-default ml-2"
                            onclick="ezyadmin.resetAddSettingModel();">[[#{reset}]]</button>
                </div>
                <button type="button" class="btn btn-primary" onclick="ezyadmin.addNewSetting();">[[#{add}]]</button>
            </div>
        </div>
        <!-- /.modal-content -->
    </div>
    <!-- /.modal-dialog -->
</div>

<div class="modal fade pt-4rem" id="edit-setting">
    <div class="modal-dialog modal-md">
        <div class="modal-content">
            <div class="modal-header">
                <h4 class="modal-title">[[#{edit_setting}]]</h4>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <form id="editSettingForm" onsubmit="return false;">
                    <div class="form-group row">
                        <label for="editSettingName" class="col-2 col-form-label">[[#{name}]]:</label>
                        <div class="col-10">
                            <label class="col-form-label text-danger d-none" id="editSettingNameErrorLabel" for="editSettingName">
                                <i class="far fa-times-circle"></i> <span id="editSettingNameError"></span>
                            </label>
                            <input type="text" name="name" id="editSettingName"
                                   class="form-control" th:placeholder="#{name}"
                                   onkeydown="ezyadmin.onKeyDownToSaveSetting('edit')">
                        </div>
                    </div>
                    <div class="form-group row">
                        <label for="editSettingDataType" class="col-2 col-form-label">
                            [[#{type}]]:
                        </label>
                        <div class="col-10">
                            <label class="col-form-label text-danger d-none" id="editSettingDataTypeErrorLabel" for="editSettingDataType">
                                <i class="far fa-times-circle"></i> <span id="editSettingDataTypeError"></span>
                            </label>
                            <select name="dataType" id="editSettingDataType" class="form-control" aria-label="Type Select"
                                    onchange="ezyadmin.onSettingValueTypeChanged(this, 'edit');">
                                <option th:each="dataType : ${dataTypes}"
                                        th:value="${dataType}">
                                    [[#{${dataType.toLowerCase()}}]]
                                </option>
                            </select>
                        </div>
                    </div>
                    <div class="form-group row mb-0">
                        <label for="editSettingValue" class="col-2 col-form-label">[[#{value}]]:</label>
                        <div class="col-10">
                            <label class="col-form-label text-danger d-none" id="editSettingValueErrorLabel" for="editSettingValue">
                                <i class="far fa-times-circle"></i> <span id="editSettingValueError"></span>
                            </label>
                            <textarea name="value" id="editSettingValue"
                                      class="form-control" th:placeholder="#{value}" rows="3"></textarea>
                            <div class="input-group cursor-pointer d-none" id="editSettingImageGroup" onclick="ezyadmin.selectSettingMedia('edit', 'image');">
                                <input type="text" name="settingImage"
                                       id="editSettingImage" class="form-control" th:placeholder="#{select_an_image}">
                                <div class="input-group-append">
                                    <div class="input-group-text">
                                        <span>[[#{browse}]]</span>
                                    </div>
                                </div>
                            </div>
                            <div class="input-group cursor-pointer d-none" id="editSettingMediaGroup" onclick="ezyadmin.selectSettingMedia('edit', 'media');">
                                <input type="text" name="settingMedia"
                                       id="editSettingMedia" class="form-control" th:placeholder="#{select_a_media}">
                                <div class="input-group-append">
                                    <div class="input-group-text">
                                        <span>[[#{browse}]]</span>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="form-group row mt-2">
                        <label for="editChangeLastUpdateTime" class="col-2 col-form-label">
                            [[#{include}]]:
                        </label>
                        <div class="col-10 d-flex align-items-center">
                            <input type="checkbox" name="changeLastUpdateTime" id="editChangeLastUpdateTime" class="form-check wh-1rem">
                            <span class="ml-1">[[#{last_update_time_of_this_setting}]]</span>
                        </div>
                    </div>
                </form>
            </div>
            <div class="modal-footer justify-content-between">
                <button type="button" class="btn btn-default" data-dismiss="modal">[[#{cancel}]]</button>
                <div class="d-flex">
                    <button type="button" class="btn btn-primary" onclick="ezyadmin.editSetting();">[[#{edit}]]</button>
                    <button type="button" class="btn btn-danger ml-2" onclick="ezyadmin.deleteSetting();">[[#{delete}]]</button>
                </div>
            </div>
        </div>
        <!-- /.modal-content -->
    </div>
    <!-- /.modal-dialog -->
</div>
</th:block>
<script layout:fragment="scripts" th:inline="javascript">
/*<![CDATA[*/
ezyadmin.settingSearchDataType = /*[[${settingSearchDataType}]]*/ '';
ezyadmin.settingSearchKeyword = /*[[${settingSearchKeyword}]]*/ '';
/*]]>*/

// ========== setting init =============
ezyadmin.onKeyDownToSaveSetting = function(action) {
    if(event.key === 'Enter') {
    	ezyadmin.saveSetting(action);
    }
}

ezyadmin.onNewButtonClick = function(e) {
    $('#addSettingDataType').val(ezyadmin.settingSearchDataType);
    $('#add-setting').modal('show');
}

ezyadmin.resetAddSettingModel = function() {
    $('#addSettingName').val('');
    $('#addSettingValue').val('');
    $('#addSettingImage').val('');
    $('#addSettingMedia').val('');
    $('#addSettingDataType').val('').change();
}

ezyadmin.selectSettingMedia = function(action, mediaType) {
    ezyadmin.currentSettingAction = action;
    $('#' + action + '-setting').modal('hide');
    ezyadmin.showMediaModal(mediaType)
        .onMediaShow(media => {
            if (mediaType == 'image' && media.type != 'IMAGE') {
                $('#selectMediaButton').attr('disabled', true);
            }
        })
        .onMediaSelected(media => {
            ezyadmin.onSettingMediaSelected(action, mediaType, media);
        });
}

ezyadmin.onSettingMediaSelected = function(action, mediaType, media) {
    var elementId = '#' + action + 'Setting' +
         mediaType[0].toUpperCase() + mediaType.substring(1);
    $(elementId).val(ezyadmin.extractMediaUrl(media));
    ezyadmin.closeMediaModal();
    $('#' + action + '-setting').modal('show');
}

$("#media-modal").on("hidden.bs.modal", function () {
    $('#' + ezyadmin.currentSettingAction + '-setting').modal('show');
});

ezyadmin.onSettingValueTypeChanged = function(e, action) {
    var dataType = $(e).val();
    $('#' + action + 'SettingValue').addClass('d-none');
    $('#' + action + 'SettingMediaGroup').addClass('d-none');
    $('#' + action + 'SettingImageGroup').addClass('d-none');
    if (dataType == 'IMAGE') {
        $('#' + action + 'SettingImageGroup').removeClass('d-none');
    } else if (dataType == 'MEDIA') {
        $('#' + action + 'SettingMediaGroup').removeClass('d-none');
    } else {
        var inputType = ezyadmin.dataTypeToInputType(dataType);
        $('#' + action + 'SettingValue')
            .attr('type', inputType)
            .removeClass('d-none');
    }
}

ezyadmin.saveSetting = function(action) {
    var data = ezyadmin.formDataToObject(action + 'SettingForm');
    if (data.dataType == 'IMAGE') {
        data.value = data.settingImage;
    } else if (data.dataType == 'MEDIA') {
        data.value = data.settingMedia;
    }
    delete data.settingImage;
    delete data.settingMedia;
    var hasError = false;
    if (!data.name) {
        $('#' + action + 'SettingNameError')
            .text(ezyadmin.getErrorMessageByCode('required'));
        $('#' + action + 'SettingNameErrorLabel').removeClass('d-none');
        hasError = true;
    } else {
        $('#' + action + 'SettingNameErrorLabel').addClass('d-none');
    }
    if (!data.dataType) {
        $('#' + action + 'SettingDataTypeError')
            .text(ezyadmin.getErrorMessageByCode('required'));
        $('#' + action + 'SettingDataTypeErrorLabel').removeClass('d-none');
        hasError = true;
    } else {
        $('#' + action + 'SettingDataTypeErrorLabel').addClass('d-none');
    }
    if (!data.value) {
        $('#' + action + 'SettingValueError')
            .text(ezyadmin.getErrorMessageByCode('required'));
        $('#' + action + 'SettingValueErrorLabel').removeClass('d-none');
        hasError = true;
    } else {
        var isValidJson = true;
        if (data.dataType == 'JSON') {
            try {
                JSON.parse(data.value);
            } catch (e) {
                isValidJson = false;
            }
        }
        if (isValidJson) {
            $('#' + action + 'SettingValueErrorLabel').addClass('d-none');
        } else {
            $('#' + action + 'SettingValueError').text(ezyadmin.messages.invalid);
            $('#' + action + 'SettingValueErrorLabel').removeClass('d-none');
            hasError = true;
        }
    }
    if (hasError) {
        return;
    }
    data.changeLastUpdateTime = $('#' + action + 'ChangeLastUpdateTime')
        .prop('checked');
    $.ajax({
        type: action == 'add' ? 'POST' : 'PUT',
        url: '/api/v1/settings/' + (action == 'add' ? 'add' : ezyadmin.selectedSettingId),
        data: JSON.stringify(data),
        contentType: 'application/json',
        success: function (responseData) {
            var setting = responseData;
            if (action == 'add') {
                ezyadmin.fetchSettingList();
            } else {
                ezyadmin.fetchSettingList('current');
            }
            $('#' + action + '-setting').modal('hide');
            ezyadmin.resetAddSettingModel();
        },
        error: function (e) {
            ezyadmin.processUpdateApiErrors(data, e);
        }
    });
}

// ========== setting add =============
ezyadmin.addNewSetting = function() {
    ezyadmin.saveSetting('add');
}

// ========== setting edit =============
ezyadmin.openSettingModal = function(settingId) {
    ezyadmin.selectedSettingId = settingId;
    var setting = ezyadmin.settingById[settingId];
    $('#editSettingName').val(setting.name);
    $('#editSettingValue').val(setting.value);
    $('#editSettingDataType').val(setting.dataType);
    $('#editSettingImage').val(setting.value);
    $('#editSettingMedia').val(setting.value);

    $('#editSettingValue').addClass('d-none');
    $('#editSettingMediaGroup').addClass('d-none');
    $('#editSettingImageGroup').addClass('d-none');
    if (setting.dataType == 'IMAGE') {
        $('#editSettingImageGroup').removeClass('d-none');
    } else if (setting.dataType == 'MEDIA') {
        $('#editSettingMediaGroup').removeClass('d-none');
    } else {
        $('#editSettingValue').removeClass('d-none');
    }
    var inputType = ezyadmin.dataTypeToInputType(setting.dataType);
    $('#editSettingValue').attr('type', inputType);
    $('#edit-setting').modal('show');
}

ezyadmin.dataTypeToInputType = function(dataType) {
    var inputType = 'text';
    if (dataType == 'PASSWORD' || dataType == 'EMAIL') {
        inputType = dataType.toLowerCase();
    }
    return inputType;
}

ezyadmin.editSetting = function() {
    ezyadmin.saveSetting('edit');
}

// ========== setting delete =============
ezyadmin.deleteSetting = function() {
    $.ajax({
        type: 'delete',
        url: '/api/v1/settings/' + ezyadmin.selectedSettingId,
        success: function () {
            delete ezyadmin.settingById[ezyadmin.selectedSettingId];
            ezyadmin.fetchSettingList('current');
            $('#edit-setting').modal('hide');
        },
        error: function (data, e) {
            $('#edit-setting').modal('hide');
        }
    });
}

// ========== setting search =============
ezyadmin.onKeydownToSearchSetting = function() {
    ezyadmin.settingSearchKeyword = $('#settingSearchKeyword').val();
    if(event.key === 'Enter' || !ezyadmin.settingSearchKeyword) {
        ezyadmin.fetchSettingList();
        ezyadmin.changeBrowserUrl();
    }
}

ezyadmin.onSettingStatusSelected = function() {
    ezyadmin.settingSearchDataType = $('#settingSearchDataType').val();
    ezyadmin.fetchSettingList();
    ezyadmin.changeBrowserUrl();
}

ezyadmin.changeBrowserUrl = function() {
    var params = [];
    if (ezyadmin.settingSearchKeyword) {
        params.push('keyword=' + ezyadmin.settingSearchKeyword);
    }
    if (ezyadmin.settingSearchDataType) {
        params.push('dataType=' + ezyadmin.settingSearchDataType);
    }
    if (ezyadmin.lang) {
        params.push('lang=' + ezyadmin.lang);
    }
    var url = location.pathname;
    if (params.length) {
        url += '?' + params.join('&');
    }
    window.history.pushState({}, '', url);
}

// ========== setting pagination =============
$('#firstPageButton').click(() => {
    ezyadmin.fetchSettingList('first');
});
$('#lastPageButton').click(() => {
    ezyadmin.fetchSettingList('last');
});
$('#nextPageButton').click(() => {
    ezyadmin.fetchSettingList('next');
});
$('#prevPageButton').click(() => {
    ezyadmin.fetchSettingList('prev');
});

// ========== setting list =============
ezyadmin.settingById = {};
ezyadmin.fetchSettingList = function(action) {
    var queryString = '';
    if (ezyadmin.settingSearchKeyword) {
        queryString += '&keyword=' + ezyadmin.settingSearchKeyword;
    }
    if (ezyadmin.settingSearchDataType) {
        queryString += '&dataType=' + ezyadmin.settingSearchDataType;
    }
    if (action == 'current') {
        if (ezyadmin.lastSettingQueryString) {
            queryString = ezyadmin.lastSettingQueryString;
        }
    } else if (action == 'next') {
        if (ezyadmin.lastSettingPageToken.next) {
            queryString += '&nextPageToken=' + ezyadmin.lastSettingPageToken.next;
        } else {
            return;
        }
    } else if (action == 'prev') {
        if (ezyadmin.lastSettingPageToken.prev) {
            queryString += '&prevPageToken=' + ezyadmin.lastSettingPageToken.prev;
        } else {
            return;
        }
    } else if (action == 'last') {
        queryString += '&lastPage=true';
    }
    $.ajax({
        url: '/api/v1/settings?limit=30' + queryString,
        type: 'GET',
        dataType: 'json'
    })
    .done(function(data) {
        $('#settingCountText').text(data.count);
        $('#totalSettingText').text(ezyadmin.formatTotalResults(data.total));
        ezyadmin.lastSettingQueryString = queryString;
        ezyadmin.lastSettingPageToken = data.pageToken;
        data.items.forEach((item) => {
            ezyadmin.settingById[item.id] = item;
        });
        $('#settingListBody').html(ezyadmin.buildSettingListBodyHtml(data.items));
        if (data.continuation.hasNext) {
            $('#nextPageButton').removeClass('text-secondary');
        } else {
            $('#nextPageButton').addClass('text-secondary');
        }
        if (data.continuation.hasPrevious) {
            $('#prevPageButton').removeClass('text-secondary');
        } else {
            $('#prevPageButton').addClass('text-secondary');
        }
    })
    .fail(function(e) {
    	ezyadmin.processGetApiErrors(e);
    });
}

ezyadmin.buildSettingListBodyHtml = function(settings) {
    var html = '';
    settings.forEach((setting) => {
        html = html + ezyadmin.buildSettingItemHtml(setting);
    });
    return html;
}

ezyadmin.buildSettingItemHtml = function(setting) {
    var html = `
        <tr id="settingItem${setting.id}">
            <td>${setting.id}</td>
            <td>
                <button type="button" class="btn btn-link" onclick="ezyadmin.openSettingModal(${setting.id})">
                    ${setting.name}
                </button>
            </td>
            <td class="text-wrap line-break-anywhere min-width-250-px">
                ${setting.value || ''}
            </td>
            <td class="text-center">${ezyadmin.getI18nMessage(setting.dataType.toLowerCase())}</td>
            <td class="text-center">${ezyadmin.formatTimeStamp(setting.updatedAt)}</td>
        </tr>
    `;
    return html;
}

ezyadmin.fetchSettingList();
</script>
</body>
</html>
