<!--
 ~ 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:th="http://www.thymeleaf.org">
<body>
<th:block th:fragment="content">
	<div th:if="${includeMediaModal != false}" class="modal fade" id="media-modal">
		<div class="modal-dialog modal-xl">
			<div class="modal-content">
				<div class="modal-header">
					<div class="d-flex">
						<h4 class="modal-title">[[#{media}]]</h4>
						<button type="button" class="btn btn-outline-primary ml-3"
						        th:if="${adminRoles.isAccessible('/api/v1/media/add', 'POST')}"
								onclick="ezyadmin.showAddNewMediaModal();">
							[[#{add_new}]]
						</button>
						<button type="button" class="btn btn-outline-info ml-3 d-none" id="selectMediasButton"
						        onclick="ezyadmin.onSelectMediasButtonClicked();">
							[[#{select}]]
						</button>
					</div>
					<button type="button" class="close" data-dismiss="modal" aria-label="Close">
						<span aria-hidden="true">&times;</span>
					</button>
				</div>
				<div class="modal-body max-height-85vn-scroll">
					<div class="px-2">
						<div class="row">
							<div class="col-lg-3 col-md-4 page-search">
								<input type="search" class="form-control"
								   id="mediaModelSearchKeywordInput"
								   th:placeholder="#{keyword}"
								   oninput="ezyadmin.onKeydownToSearchMedia(this);"
								   onkeydown="ezyadmin.onKeydownToSearchMedia(this);">
							</div>
							<div class="col-lg-3 col-md-4 page-search">
								<input type="search" class="form-control"
								       id="mediaModelSearchGroupNamePrefixInput"
								       th:placeholder="#{group_name}"
								       oninput="ezyadmin.onKeydownToSearchMediaGroupNamePrefix(this);"
								       onkeydown="ezyadmin.onKeydownToSearchMediaGroupNamePrefix(this);">
							</div>
							<div class="col-lg-3 col-md-4 page-search">
								<select class="form-control" id="mediaModelSearchTypeSelect"
										onchange="ezyadmin.onSearchMediaTypeChanged(this);">
									<option value="">[[#{all_type}]]</option>
									<option th:each="searchMediaType : ${searchMediaTypes}"
											th:value="${searchMediaType}">
										[[#{${searchMediaType.toString().toLowerCase()}}]]
									</option>
								</select>
							</div>
							<div class="col-lg-3 col-md-4 page-search">
								<select class="form-control" id="mediaModelSearchStatusSelect"
										onchange="ezyadmin.onSearchMediaStatusChanged(this);">
									<option value="">[[#{status}]]</option>
									<option th:each="searchStatus : ${searchMediaStatuses}"
											th:value="${searchStatus}">
										[[#{${searchStatus.toString().toLowerCase()}}]]
									</option>
								</select>
							</div>
							<div class="col-lg-3 col-md-4 page-search">
								<input type="text" class="form-control"
								       id="mediaModelSearchDatePicker"
								       th:placeholder="#{date}">
							</div>
							<div class="col-lg-3 col-md-4 page-search">
								<input type="text" class="form-control"
								       id="mediaModelSearchTimeRangePicker"
								       th:placeholder="#{time_range}">
							</div>
							<div class="col-lg-3 col-md-4 page-search">
								<select class="form-control"
										onchange="ezyadmin.onSearchMediaSortOrderChanged(this);">
									<option value="">[[#{sort_by}]]</option>
									<option th:each="sortOrder : ${searchMediaSortOrders}"
											th:value="${sortOrder}">
										[[#{'sort_by_' + ${sortOrder.toString().toLowerCase()}}]]
									</option>
								</select>
							</div>
							<div class="col-lg-3 col-md-4 page-search">
								<select class="form-control" id="mediaModelDisplayTypeSelect"
										onchange="ezyadmin.onMediaDisplayTypeChanged(this);">
									<option value="ICONS">[[#{display_type}]]</option>
									<option value="ICONS" selected>
										[[#{display_type_icons}]]
									</option>
									<option value="LIST">
										[[#{display_type_list}]]
									</option>
								</select>
							</div>
							<div class="col-lg-3 col-md-4 page-search">
								<select class="form-control" id="mediaModelSearchLimit"
										onchange="ezyadmin.onSearchMediaLimitChanged(this);">
									<option th:value="${numberOfMediaPerPage}" selected>
										[[#{limit}]]
									</option>
									<option value="30">30 [[#{item_s}]]</option>
									<option value="50">50 [[#{item_s}]]</option>
									<option value="100">100 [[#{item_s}]]</option>
									<option value="200">200 [[#{item_s}]]</option>
									<option value="300">300 [[#{item_s}]]</option>
									<option value="400">400 [[#{item_s}]]</option>
									<option value="500">500 [[#{item_s}]]</option>
								</select>
							</div>
							<div th:if="${allowReduceMediaFileSize}" class="col-lg-3 col-md-4 page-search reduce-selected-media-files-button-wrapper d-none">
								<button type="button" class="btn btn-primary form-control"
										onclick="ezyadmin.onReduceSelectedMediaFilesClick();">
									[[#{reduce_file_size_button_title}]]
								</button>
							</div>
						</div>
					</div>
					<div class="selected-media-count-text-wrapper d-none py-2">
						<span class="selected-media-count-text"></span>
					</div>
					<div class="text-center">
						<ul class="media-list" id="mediaListBody"></ul>
					</div>
					<div class="d-flex flex-column text-center">
						<span>
							[[#{showing}]]
							<span id="mediaCountText">0</span>
							[[${#strings.toLowerCase(#messages.msg('of'))}]]
							<span id="totalMediaText">0</span>
							[[${#strings.toLowerCase(#messages.msg('media_items'))}]]
						</span>
						<div>
							<button type="button" class="btn btn-primary pl-5 pr-5 mt-2 mb-3 d-none" id="loadMoreMediaButton">
								[[#{load_more}]]
							</button>
						</div>
					</div>
				</div>
			</div>
		</div>
	</div>

	<div class="modal fade pt-4rem" id="add-new-media">
		<div class="modal-dialog modal-md">
			<div class="modal-content">
				<div class="modal-header">
					<h4 class="modal-title">[[#{add_new_media}]]</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="addNewMediaForm" method="post" enctype="multipart/form-data">
						<label id="addMediaFileErrorLabel" class="col-form-label text-danger pt-0 d-none" for="addMediaFile">
							<i class="far fa-times-circle"></i> <span class="line-break-anywhere" id="addMediaFileError">[[#{invalid}]]</span>
						</label>
						<div class="input-group">
							<div class="custom-file">
								<input name="file" type="file" id="addMediaFile"
									   class="custom-file-input" multiple>
								<label class="custom-file-label" for="addMediaFile" id="addMediaFileLabel">
									[[#{select_a_file}]]
								</label>
							</div>
						</div>
						<div class="d-flex align-items-center mt-2">
							<input type="checkbox" name="notPublicMedia" id="notPublicMedia" class="form-check wh-1rem">
							<span class="ml-2">[[#{not_public_for_every_user}]]</span>
						</div>
						<div class="d-flex justify-content-center py-4">
							<h5>[[#{or_add_from_url}]]</h5>
						</div>
						<div class="form-group row">
							<label for="addMediaUrlType" class="col-3 col-form-label">
								[[#{type}]] (<span class="text-danger">*</span>):
							</label>
							<div class="col-9">
								<label class="col-form-label text-danger d-none" id="addMediaUrlTypeErrorLabel" for="addMediaUrlType">
									<i class="far fa-times-circle"></i> <span id="addMediaUrlTypeError"></span>
								</label>
								<select name="type" id="addMediaUrlType" class="form-control" aria-label="Type Select"
										onchange="ezyadmin.onAddMediaTypeChanged(this);">
									<option th:each="commonMediaType : ${commonMediaTypes}"
											th:value="${commonMediaType}">
										[[#{${commonMediaType.toString().toLowerCase()}}]]
									</option>
								</select>
							</div>
						</div>
						<div class="form-group row">
							<label for="addMediaUrlName" class="col-3 col-form-label">
								[[#{name}]] (<span class="text-danger">*</span>):
							</label>
							<div class="col-9">
								<label class="col-form-label text-danger d-none" id="addMediaUrlNameErrorLabel" for="addMediaUrlName">
									<i class="far fa-times-circle"></i> <span id="addMediaUrlNameError"></span>
								</label>
								<input type="text" name="originalName" id="addMediaUrlName"
									   class="form-control" th:placeholder="#{name}"
									   onkeydown="ezyadmin.onKeyDownToAddNewMedia()">
							</div>
						</div>
						<div class="form-group row mb-0">
							<label for="addMediaUrlValue" class="col-3 col-form-label">
								[[#{url}]] (<span class="text-danger">*</span>):
							</label>
							<div class="col-9">
								<label class="col-form-label text-danger d-none" id="addMediaUrlValueErrorLabel" for="addMediaUrlValue">
									<i class="far fa-times-circle"></i> <span id="addMediaUrlValueError"></span>
								</label>
								<input type="text" name="url" id="addMediaUrlValue"
									   class="form-control" th:placeholder="#{url}"
									   onkeydown="ezyadmin.onKeyDownToAddNewMedia('add')">
							</div>
						</div>
						<div class="form-group row mt-3 mb-0" id="addMediaUrlDurationWrapper">
							<label for="addMediaUrlDuration" class="col-3 col-form-label">
								[[#{duration}]]
							</label>
							<div class="col-9">
								<label class="col-form-label text-danger d-none" id="addMediaUrlDurationErrorLabel" for="addMediaUrlDuration">
									<i class="far fa-times-circle"></i> <span id="addMediaUrlDurationError"></span>
								</label>
								<input type="text" name="durationInMinutes" id="addMediaUrlDuration"
									   class="form-control" th:placeholder="#{time_in_minutes}"
									   onkeydown="ezyadmin.onKeyDownToAddNewMedia('add')">
							</div>
						</div>
					</form>
				</div>
				<div class="modal-footer justify-content-between">
					<button type="button" class="btn btn-default" data-dismiss="modal">[[#{cancel}]]</button>
					<button type="button" class="btn btn-primary" onclick="ezyadmin.addNewMedias();">[[#{add}]]</button>
				</div>
			</div>
			<!-- /.modal-content -->
		</div>
		<!-- /.modal-dialog -->
	</div>

	<div class="modal fade" id="media-details">
		<div class="modal-dialog modal-xl">
			<div class="modal-content">
				<div class="modal-header">
					<h4 class="modal-title">[[#{media_details}]]</h4>
					<button type="button" class="close" data-dismiss="modal" aria-label="Close">
						<span aria-hidden="true">&times;</span>
					</button>
				</div>
				<div class="modal-body row">
					<div class="col-lg-7 mb-2">
						<div class="text-center max-height-75vn-scroll" id="mediaDetailsBody"></div>
						<div class="d-flex justify-content-center flex-wrap gap-2 pt-3">
							<button th:if="${allowReduceMediaFileSize}"
									type="button" class="btn btn-outline-primary"
									onclick="ezyadmin.onReduceMediaFileSizeClick();">
								[[#{reduce_file_size_button_title}]]
							</button>
							<button type="button" class="btn btn-outline-secondary"
									onclick="ezyadmin.onReplaceMediaClick();">
								[[#{replace}]]
							</button>
							<button type="button" class="btn btn-outline-danger"
									id="deleteMediaOnDetailsButton"
									onclick="ezyadmin.deleteMedia();">
								[[#{delete}]]
							</button>
							<button type="button" class="btn btn-outline-success d-none"
									id="restoreMediaButton" onclick="ezyadmin.restoreMedia();">
								[[#{restore}]]
							</button>
							<a class="btn btn-outline-info d-none" id="viewExternalMediaButton" target="_blank">
								[[#{view}]]
								<i class="fas fa-external-link-alt"></i>
							</a>
						</div>
						<div id="reduceMediaFileSizeArea"
							 class="d-none align-items-center pt-3">
							<input type="range" class="custom-range"
								   id="reduceMediaFileSizeRange"
								   oninput="ezyadmin.onReduceMediaFileSizeInputChanged();">
							<span id="reduceMediaFileSizeText"
								  class="ml-2 text-nowrap"></span>
							<button type="button" class="btn btn-outline-success ml-2 text-nowrap"
									onclick="ezyadmin.reduceMediaFileSize();">
								[[#{apply}]]
							</button>
						</div>
						<input type="file" class="d-none" id="replaceMediaFileInput" onchange="ezyadmin.replaceMedia();">
						<div id="embedMediaScriptArea">
							<span>[[#{embed_script}]]</span>
							<textarea id="embedMediaScript" class="form-control" rows="5"></textarea>
							<div class="d-flex justify-content-center pt-2">
								<button class="btn btn-outline-primary" onclick="ezyadmin.copyEmbedMediaScript();">
									[[#{copy_script}]]
								</button>
							</div>
						</div>
					</div>
					<div class="col-lg-5 bg-light pl-2 pr-2 font-size-95">
						<div class="row">
							<div class="col-12 row">
								<label class="col-4 pr-0">[[#{id}]]:</label><span id="mediaDetailsId" class="col-8 fit-text"></span>
							</div>
							<div class="col-12 row d-none" id="originalSizeFileRow">
								<label class="col-4 pr-0">[[#{original_size_file}]]:</label>
								<a id="originalSizeFile" class="col-8 fit-text" target="_blank"></a>
							</div>
							<div class="col-12 row">
								<label class="col-4 pr-0">[[#{file_type}]]:</label><span id="fileType" class="col-8 fit-text"></span>
							</div>
							<div class="col-12 row">
								<label class="col-4 pr-0">[[#{file_size}]]:</label><span id="fileSize" class="col-8"></span>
							</div>
							<div class="col-12 row">
								<label class="col-4 pr-0">[[#{dimension}]]:</label><span id="dimension" class="col-8"></span>
							</div>
							<div class="col-12 row">
								<label class="col-4 pr-0">[[#{upload_by}]]:</label><span id="uploadedBy" class="col-8"></span>
							</div>
							<div class="col-12 row">
								<label class="col-4 pr-0">[[#{upload_on}]]:</label><span id="uploadedOn" class="col-8"></span>
							</div>
						</div>
						<hr class="mt-2 mb-2"/>
						<form id="updateMediaForm" onsubmit="return false;">
							<div class="row">
								<div class="col-12">
									<div class="form-group row mb-1">
										<label for="updateMediaOriginalName" class="col-md-4 col-form-label">[[#{file_name}]]</label>
										<div class="col-md-8">
											<label id="updateMediaOriginalNameErrorLabel" class="col-form-label text-danger d-none" for="updateMediaOriginalName">
												<i class="far fa-times-circle"></i> <span id="updateMediaOriginalNameError"></span>
											</label>
											<input type="text" name="originalName" id="updateMediaOriginalName" class="form-control" th:placeholder="#{file_name}">
										</div>
									</div>
									<div class="form-group row mb-1">
										<label for="updateMediaType" class="col-md-4 col-form-label">[[#{type}]]</label>
										<div class="col-md-8">
											<label id="updateMediaTypeError" class="col-form-label text-danger d-none" for="updateMediaType">
												<i class="far fa-times-circle"></i>
											</label>
											<select  name="type" id="updateMediaType" class="form-control">
												<option th:each="commonMediaType : ${commonMediaTypes}"
														th:value="${commonMediaType}">
													[[#{${commonMediaType.toString().toLowerCase()}}]]
												</option>
											</select>
										</div>
									</div>
									<div class="form-group row mb-1 d-none" id="updateMediaDurationWrapper">
										<label for="updateMediaDuration" class="col-md-4 col-form-label">[[#{media_duration}]]</label>
										<div class="col-md-8">
											<label id="updateMediaDurationErrorLabel" class="col-form-label text-danger d-none" for="updateMediaDuration">
												<i class="far fa-times-circle"></i> <span id="updateMediaDurationError"></span>
											</label>
											<input type="text" name="durationInMinutes" id="updateMediaDuration" class="form-control" th:placeholder="#{media_duration}">
											<span>[[#{time_in_minutes}]]</span>
										</div>
									</div>
									<div class="form-group row mb-1">
										<label for="updateMediaGroupName" class="col-md-4 col-form-label">[[#{group_name}]]</label>
										<div class="col-md-8">
											<label id="updateMediaGroupNameErrorLabel" class="col-form-label text-danger d-none" for="updateMediaGroupName">
												<i class="far fa-times-circle"></i> <span id="updateMediaGroupNameError"></span>
											</label>
											<input type="text" name="groupName" id="updateMediaGroupName" class="form-control" th:placeholder="#{group_name}">
										</div>
									</div>
									<div class="form-group row mb-1">
										<label for="updateMediaAlternativeText" class="col-md-4 col-form-label">[[#{alter}]]</label>
										<div class="col-md-8">
											<label id="updateMediaAlternativeTextErrorLabel" class="col-form-label text-danger d-none" for="updateMediaAlternativeText">
												<i class="far fa-times-circle"></i> <span id="updateMediaAlternativeTextError"></span>
											</label>
											<input type="text" name="alternativeText" id="updateMediaAlternativeText" class="form-control" th:placeholder="#{alternative_text}">
										</div>
									</div>
									<div class="form-group row mb-1">
										<label for="updateMediaTitle" class="col-md-4 col-form-label">[[#{title}]]</label>
										<div class="col-md-8">
											<label id="updateMediaTitleErrorLabel" class="col-form-label text-danger d-none" for="updateMediaTitle">
												<i class="far fa-times-circle"></i> <span id="updateMediaTitleError"></span>
											</label>
											<input type="text" name="title" id="updateMediaTitle" class="form-control" th:placeholder="#{title}">
										</div>
									</div>
									<div class="form-group row mb-1">
										<label for="updateMediaCaption" class="col-md-4 col-form-label">[[#{caption}]]</label>
										<div class="col-md-8">
											<label id="updateMediaCaptionErrorLabel" class="col-form-label text-danger d-none" for="updateMediaCaption">
												<i class="far fa-times-circle"></i> <span id="updateMediaCaptionError"></span>
											</label>
											<textarea name="caption" id="updateMediaCaption" class="form-control" th:placeholder="#{caption}"></textarea>
										</div>
									</div>
									<div class="form-group row mb-1">
										<label for="updateMediaDescription" class="col-md-4 col-form-label">[[#{description}]]</label>
										<div class="col-md-8">
											<label id="updateMediaDescriptionErrorLabel" class="col-form-label text-danger d-none" for="updateMediaDescription">
												<i class="far fa-times-circle"></i> <span id="updateMediaDescriptionError"></span>
											</label>
											<textarea name="description" id="updateMediaDescription" class="form-control" th:placeholder="#{description}"></textarea>
										</div>
									</div>
									<div class="form-group row mb-1">
										<label for="updateNotPublicMedia" class="col-md-4 col-form-label"></label>
										<div class="col-md-8 d-flex align-items-center">
											<input type="checkbox" name="notPublicMedia" id="updateNotPublicMedia" class="form-check">
											<span class="ml-2">[[#{not_public_for_every_user}]]</span>
										</div>
									</div>
									<div class="form-group row mb-1">
										<label for="adminOriginalUrlPath" class="col-md-4 col-form-label">[[#{admin_original_url_path}]]</label>
										<div class="col-md-8 d-flex align-items-center">
											<a id="adminOriginalUrlPath" class="media-url-path flex-grow-1" target="_blank"></a>
											<button type="button" class="btn btn-link text-dark p-0 ml-2"
													th:title="#{copy_url}"
													onclick="ezyadmin.copyMediaUrlPath('adminOriginalUrlPath');">
												<i class="far fa-copy"></i>
											</button>
										</div>
									</div>
									<div class="form-group row mb-1">
										<label for="adminRandomUrlPath" class="col-md-4 col-form-label">[[#{admin_random_url_path}]]</label>
										<div class="col-md-8 d-flex align-items-center">
											<a id="adminRandomUrlPath" class="media-url-path flex-grow-1" target="_blank"></a>
											<button type="button" class="btn btn-link text-dark p-0 ml-2"
													th:title="#{copy_url}"
													onclick="ezyadmin.copyMediaUrlPath('adminRandomUrlPath');">
												<i class="far fa-copy"></i>
											</button>
										</div>
									</div>
									<div class="form-group row mb-1">
										<label for="webOriginalUrlPath" class="col-md-4 col-form-label">[[#{web_original_url_path}]]</label>
										<div class="col-md-8 d-flex align-items-center">
											<a id="webOriginalUrlPath" class="media-url-path flex-grow-1" target="_blank"></a>
											<button type="button" class="btn btn-link text-dark p-0 ml-2"
													th:title="#{copy_url}"
													onclick="ezyadmin.copyMediaUrlPath('webOriginalUrlPath');">
												<i class="far fa-copy"></i>
											</button>
										</div>
									</div>
									<div class="form-group row mb-1">
										<label for="updateMediaUrl" class="col-md-4 col-form-label">[[#{media_url}]]</label>
									   	<div class="col-md-8">
											<label class="col-form-label text-danger d-none" id="updateMediaUrlErrorLabel" for="updateMediaUrl">
												<i class="far fa-times-circle"></i> <span id="updateMediaUrlError"></span>
											</label>
											<input type="text" name="url" id="updateMediaUrl"
												   class="form-control" th:placeholder="#{media_url}">
										</div>
									</div>
									<div class="form-group row">
										<div class="col-md-4"></div>
										<div class="col-lg-4 col-md-9 pt-sm-0 pt-1" th:if="${currentMenu == 'media'}">
											<button type="button" class="btn btn-primary w-100 white-space-nowrap"
													onclick="ezyadmin.copyMediaUrl();">
												[[#{copy_url}]]
											</button>
										</div>
										<div class="col-lg-4 col-md-9 pt-sm-0 pt-1" th:if="${currentMenu != 'media'}">
											<button type="button" class="btn btn-primary w-100" id="selectMediaButton"
													onclick="ezyadmin.selectMedia();">
												[[#{select}]]
											</button>
										</div>
										<div class="d-lg-none d-md-block col-md-3 d-none"></div>
										<div class="col-lg-4 col-md-9 pt-lg-0 pt-md-1 pt-1">
											<button type="button" class="btn btn-outline-primary w-100 text-primary-always"
													onclick="ezyadmin.updateMedia();">[[#{update}]]</button>
										</div>
										<div class="col-lg-1"></div>
									</div>
								</div>
							</div>
						</form>
					</div>
				</div>
			</div>
			<!-- /.modal-content -->
		</div>
		<!-- /.modal-dialog -->
	</div>
	<!-- /.modal -->
	<div class="modal fade pt-4rem" role="dialog" id="reduce-selected-media-files-confirmation">
		<div class="modal-dialog" role="document">
			<div class="modal-content">
				<div class="modal-header">
					<h5 class="modal-title">[[#{confirmation}]]</h5>
					<button type="button" class="close" data-dismiss="modal" aria-label="Close">
						<span aria-hidden="true">&times;</span>
					</button>
				</div>
				<div class="modal-body">
					<span id="reduce-selected-media-files-confirmation-body-content">[[${body}]]</span>
				</div>
				<div class="modal-footer">
					<button type="button" class="btn btn-primary"
							onclick="ezyadmin.onReduceSelectedMediaFilesPromptConfirmed()">
						[[#{confirm}]]
					</button>
					<button type="button" class="btn btn-secondary" data-dismiss="modal">
						[[#{cancel}]]
					</button>
				</div>
			</div>
		</div>
	</div>
</th:block>
<script th:fragment="scripts" th:inline="javascript">
/*<![CDATA[*/
ezyadmin.allowReduceMediaFileSize = /*[[${allowReduceMediaFileSize}]]*/;
ezyadmin.allowPermanentlyDeleteMedia = /*[[${allowPermanentlyDeleteMedia}]]*/;
ezyadmin.numberOfMediaPerPage = /*[[${numberOfMediaPerPage}]]*/;
ezyadmin.maxReducedImageFileSize = /*[[${maxReducedImageFileSize}]]*/;
ezyadmin.messages.action = /*[[#{action}]]*/;
ezyadmin.messages.administrator = /*[[#{administrator}]]*/;
ezyadmin.messages.click_to_view_full_screen_and_zoom = /*[[#{click_to_view_full_screen_and_zoom}]]*/;
ezyadmin.messages.delete_successfully = /*[[#{delete_successfully}]]*/;
ezyadmin.messages.delete_failed = /*[[#{delete_failed}]]*/;
ezyadmin.messages.do_you_want_to_reduce_selected_media_file_size = /*[[#{do_you_want_to_reduce_selected_media_file_size}]]*/;
ezyadmin.messages.file_size = /*[[#{file_size}]]*/;
ezyadmin.messages.name = /*[[#{name}]]*/;
ezyadmin.messages.next = /*[[#{next}]]*/;
ezyadmin.messages.previous = /*[[#{previous}]]*/;
ezyadmin.messages.reduce_file_size_failed_message = /*[[#{reduce_file_size_failed_message}]]*/;
ezyadmin.messages.reduced_the_file_size_of_files_summary = /*[[#{reduced_the_file_size_of_files_summary}]]*/;
ezyadmin.messages.script = /*[[#{script}]]*/;
ezyadmin.messages.selected_pcount_medias = /*[[#{selected_pcount_medias}]]*/;
ezyadmin.messages.type = /*[[#{type}]]*/;
ezyadmin.messages.update_successfully = /*[[#{update_successfully}]]*/;
ezyadmin.messages.update_failed = /*[[#{update_failed}]]*/;
ezyadmin.messages.updated_at = /*[[#{updated_at}]]*/;
ezyadmin.messages.upload_by = /*[[#{upload_by}]]*/;
ezyadmin.messages.user = /*[[#{user}]]*/;
ezyadmin.messages.zoom = /*[[#{zoom}]]*/;
ezyadmin.accessibleUris['/api/v1/media/list'] = /*[[${adminRoles.isAccessible('/api/v1/media/list')}]]*/;
ezyadmin.accessibleUris['/api/v1/media/{name}'] = /*[[${adminRoles.isAccessible('/api/v1/media/{name}')}]]*/;
ezyadmin.accessibleUris['/api/v1/media/{id}/details'] = /*[[${adminRoles.isAccessible('/api/v1/media/{id}/details')}]]*/;
ezyadmin.accessibleUris['/api/v1/media/{id}/edit'] = /*[[${adminRoles.isAccessible('/api/v1/media/{id}', 'PUT')}]]*/;
ezyadmin.accessibleUris['/api/v1/media/{id}/delete'] = /*[[${adminRoles.isAccessible('/api/v1/media/{id}', 'DELETE')}]]*/;
ezyadmin.accessibleUris['/api/v1/media/{id}/replace'] = /*[[${adminRoles.isAccessible('/api/v1/media/{id}/replace', 'POST')}]]*/;
ezyadmin.accessibleUris['/api/v1/media/{id}/reduce-file-size'] = /*[[${adminRoles.isAccessible('/api/v1/media/{id}/reduce-file-size', 'POST')}]]*/;
ezyadmin.accessibleUris['/api/v1/media/{id}/restore'] = /*[[${adminRoles.isAccessible('/api/v1/media/{id}/restore', 'PUT')}]]*/;
/*]]>*/

$('#media-details').on('hidden.bs.modal', function (e) {
	var items = $('.playable-media-item');
	for(var i = 0 ; i < items.length ; ++i) {
		items[i].pause();
	}
});

$(document).on('keydown.ezyadminMediaDetails', function(event) {
	if (event.key === 'Escape') {
		if ($('#media-modal').hasClass('show')) {
			$('#media-modal').modal('hide');
		}
		if ($('#media-details').hasClass('show')) {
			$('#media-details').modal('hide');
		}
	}
});

// =========== filter ==========
ezyadmin.clearMediaDateFilters = function() {
	ezyadmin.searchMediaCreatedAtStartInclusive = 0;
	ezyadmin.searchMediaCreatedAtEndInclusive = 0;
}

ezyadmin.onMediaDateFilterInputChanged = function(e) {
	if ($(e).val()) {
		return;
	}
	ezyadmin.clearMediaDateFilters();
	ezyadmin.fetchMediaList(true);
}

$(document).ready(() => {
	ezyadmin.createDateRangePicker(
		'#mediaModelSearchDatePicker',
		{
			singleDatePicker: true,
			autoUpdateInput: false
		},
		function(start) {
			$('#mediaModelSearchDatePicker').val(start.format(ezyadmin.defaultDateFormat));
			$('#mediaModelSearchTimeRangePicker').val('');
			ezyadmin.searchMediaCreatedAtStartInclusive = start.clone().startOf('day').unix() * 1000;
			ezyadmin.searchMediaCreatedAtEndInclusive = start.clone().endOf('day').unix() * 1000;
			ezyadmin.fetchMediaList(true);
		}
	);
	$('#mediaModelSearchDatePicker').on('cancel.daterangepicker', function() {
		ezyadmin.clearMediaDateFilters();
		$(this).val('');
		ezyadmin.fetchMediaList(true);
	});
	$('#mediaModelSearchDatePicker').on('input', function() {
		ezyadmin.onMediaDateFilterInputChanged(this);
	});
	ezyadmin.createDateRangePicker(
		'#mediaModelSearchTimeRangePicker',
		{
			autoUpdateInput: false
		},
		function(start, end) {
			$('#mediaModelSearchTimeRangePicker').val(
				start.format(ezyadmin.defaultDateFormat)
				+ ' - '
				+ end.format(ezyadmin.defaultDateFormat)
			);
			$('#mediaModelSearchDatePicker').val('');
			ezyadmin.searchMediaCreatedAtStartInclusive = start.unix() * 1000;
			ezyadmin.searchMediaCreatedAtEndInclusive = end.unix() * 1000;
			ezyadmin.fetchMediaList(true);
		}
	);
	$('#mediaModelSearchTimeRangePicker').on('cancel.daterangepicker', function() {
		ezyadmin.clearMediaDateFilters();
		$(this).val('');
		ezyadmin.fetchMediaList(true);
	});
	$('#mediaModelSearchTimeRangePicker').on('input', function() {
		ezyadmin.onMediaDateFilterInputChanged(this);
	});
});


// =========== show media modal ==========
ezyadmin.mediaSelectedHandlers = {};
ezyadmin.showMediaModal = function(command) {
	ezyadmin.mediaCount = 0;
	ezyadmin.mediaTotal = 0;
	ezyadmin.lastNextPageToken = '';
	ezyadmin.mediaDisplayType = 'ICONS';
	ezyadmin.searchMediaKeyword = '';
	ezyadmin.searchMediaGroupNamePrefix = '';
	ezyadmin.searchMediaType = '';
	ezyadmin.searchMediaStatus = '';
	ezyadmin.clearMediaDateFilters();
	$('#mediaModelSearchKeywordInput').val('');
	$('#mediaModelSearchGroupNamePrefixInput').val('');
	$('#mediaModelSearchTypeSelect').val('');
	$('#mediaModelSearchStatusSelect').val('');
	$('#mediaModelDisplayTypeSelect').val(ezyadmin.mediaDisplayType);
	$('#mediaModelSearchDatePicker').val('');
	$('#mediaModelSearchTimeRangePicker').val('');
	$('#mediaListBody').html('');
	ezyadmin.fetchMediaList(true);
	$('#media-modal').modal('show');
	var handler = {};
	handler.onMediaShow = function (callback) {
		handler.showCallback = callback;
		return handler;
	};
	handler.onMediaModelHide = function (callback) {
		handler.mediaModalHideCallback = callback;
		return handler;
	};
	handler.onMediaSelected = function (callback) {
		handler.selectCallback = callback;
		return handler;
	};
	handler.onMultipleMediaSelected = function (callback) {
		handler.selectMultipleCallback = callback;
		return handler;
	};
	var actualCommand = command || '';
	ezyadmin.mediaSelectedHandlers[actualCommand] = handler;
	ezyadmin.currentMediaSelectedCommand = actualCommand;
	return handler;
}

ezyadmin.closeMediaModal = function() {
	$('#media-modal').modal('hide');
	$('#media-details').modal('hide');
}

$('#media-modal').on('hidden.bs.modal', function () {
    var handler = ezyadmin.mediaSelectedHandlers[ezyadmin.currentMediaSelectedCommand];
	if (handler) {
		var mediaModalHideCallback = handler.mediaModalHideCallback;
		if (mediaModalHideCallback) {
			mediaModalHideCallback();
		}
	}
});

ezyadmin.selectMedia = function() {
	ezyadmin.mediaSelectedHandlers[ezyadmin.currentMediaSelectedCommand]?.selectCallback(ezyadmin.selectedMedia);
}

// ========== add new =============
ezyadmin.addMediaView = {
    name: 'addMedia',
    chooseFileLabelText: $('#addMediaFileLabel').text()
};
bsCustomFileInput.init();

$(document).ready(() => {
	$('#addMediaFile').on('click', function() {
    	$(this).val('');
	});
});

ezyadmin.showAddNewMediaModal = function() {
	ezyadmin.resetFormData({
		addMediaUrlName: true,
		addMediaUrlValue: true,
		addMediaUrlDuration: true
	});
	$('#addMediaFileErrorLabel').addClass('d-none');
	$('#notPublicMedia').prop('checked', false);
	$('#add-new-media').modal('show');
}

ezyadmin.onAddMediaTypeChanged = function(e) {
	var mediaType = $(e).val();
	if (mediaType == 'VIDEO' || mediaType == 'AUDIO') {
		$('#addMediaUrlDurationWrapper').removeClass('d-none');
	} else {
		$('#addMediaUrlDurationWrapper').addClass('d-none');
	}
}

ezyadmin.addNewMedias = function() {
	$('#fileErrorLabel').addClass('d-none');
	var notPublicMedia = $('#notPublicMedia').prop('checked');
    $.each($('#addMediaFile')[0].files, function(index, file) {
        ezyadmin.addNewMedia(file, notPublicMedia);
    });
    var formData = ezyadmin.formDataToObject('addNewMediaForm');
    delete formData.file;
    if (formData.url.trim()) {
		ezyadmin.addNewMediaFromUrl(formData, notPublicMedia);
    }
}

ezyadmin.addNewMediaAsync = function(file, notPublicMedia, options) {
    return new Promise((resolve, reject) => {
        ezyadmin.addNewMedia(file, notPublicMedia, {
            ...options,
            onSuccess: (media) => resolve(media),
            onFailed: (e) => reject(e)
        });
    });
};

ezyadmin.addNewMedia = function(file, notPublicMedia, options) {
	ezyadmin.showLoadingScreen({showPercent: true});
    var data = new FormData();
    data.append('file', file);
    $.ajax({
        type: "POST",
        enctype: 'multipart/form-data',
        url: "/api/v1/media/add?notPublic=" + notPublicMedia,
        data: data,
        processData: false,
        contentType: false,
        cache: false,
        xhr: function () {
            var xhr = new window.XMLHttpRequest();
            xhr.upload.addEventListener('progress', function(event) {
                if (event.lengthComputable) {
                    var percentComplete = Math.round((event.loaded / event.total) * 100);
                    ezyadmin.setLoadingScreenPercent(percentComplete);
                }
            });
            return xhr;
        },
        success: function (data) {
            $('#add-new-media').modal('hide');
            $('#addMediaFileLabel').text(ezyadmin.addMediaView.chooseFileLabelText);
            var media = JSON.parse(data);
            ezyadmin.mediaById[media.id] = media;
            ezyadmin.mediaList = [media].concat(
            	ezyadmin.mediaList.filter((item) => item.id !== media.id)
            );
            ezyadmin.appendToMediaListTable([media], true);
            $('#mediaCountText').text(++ ezyadmin.mediaCount);
            $('#totalMediaText').text(++ ezyadmin.mediaTotal);
            ezyadmin.setLoadingScreenPercent(100);
            ezyadmin.hideLoadingScreen();
            var onSuccess = options?.onSuccess;
            if (onSuccess) {
				onSuccess(media);
            }
        },
        error: function(e) {
            ezyadmin.processUploadFileApiErrors(e, ezyadmin.addMediaView);
            ezyadmin.hideLoadingScreen();
            var onFailed = options?.onFailed;
            if (onFailed) {
            	onFailed(e);
            }
        }
    });
}

ezyadmin.onKeyDownToAddNewMedia = function() {
	if(event.key === 'Enter') {
		var notPublicMedia = $('#notPublicMedia').prop('checked');
		var formData = ezyadmin.formDataToObject('addNewMediaForm');
		delete formData.file;
		ezyadmin.addNewMediaFromUrl(formData, notPublicMedia);
    }
}

ezyadmin.addNewMediaFromUrl = function(formData, notPublicMedia) {
	var mediaType = formData.type;
	formData.saveDuration = mediaType == 'VIDEO' || mediaType == 'AUDIO';
    $.ajax({
        type: "POST",
        url: "/api/v1/media/add-from-url?notPublic=" + notPublicMedia,
        contentType: 'application/json',
        data: JSON.stringify(formData),
        success: function (media) {
            $('#add-new-media').modal('hide');
            ezyadmin.mediaById[media.id] = media;
            ezyadmin.mediaList = [media].concat(
            	ezyadmin.mediaList.filter((item) => item.id !== media.id)
            );
            ezyadmin.appendToMediaListTable([media], true);
            $('#mediaCountText').text(++ ezyadmin.mediaCount);
            $('#totalMediaText').text(++ ezyadmin.mediaTotal);
        },
        error: function(e) {
        	var formView = {
        		addMediaUrlName: true,
        		addMediaUrlValue: true,
        		addMediaUrlDuration: true
        	};
        	var errors = e.responseJSON || {};
        	errors.addMediaUrlName = errors.originalName;
			errors.addMediaUrlValue = errors.url;
			errors.addMediaUrlDuration = errors.durationInMinutes;
            ezyadmin.processUpdateApiErrors(formView, e);
        }
    });
}

// =============== search media ==========
ezyadmin.onKeydownToSearchMedia = function(e) {
	var before = ezyadmin.searchMediaKeyword;
	ezyadmin.searchMediaKeyword = $(e).val();
	if(event.key === 'Enter' || (before && !ezyadmin.searchMediaKeyword)) {
		ezyadmin.fetchMediaList(true);
    }
}

ezyadmin.onKeydownToSearchMediaGroupNamePrefix = function(e) {
	var before = ezyadmin.searchMediaGroupNamePrefix;
	ezyadmin.searchMediaGroupNamePrefix = $(e).val();
	if(event.key === 'Enter' || (before && !ezyadmin.searchMediaGroupNamePrefix)) {
		ezyadmin.fetchMediaList(true);
    }
}

ezyadmin.onSearchMediaTypeChanged = function(e) {
	ezyadmin.searchMediaType = $(e).val();
	ezyadmin.fetchMediaList(true);
}

ezyadmin.onSearchMediaStatusChanged = function(e) {
	ezyadmin.searchMediaStatus = $(e).val();
	ezyadmin.fetchMediaList(true);
}

ezyadmin.onSearchMediaSortOrderChanged = function(e) {
	ezyadmin.searchMediaSortOrder = $(e).val();
	ezyadmin.fetchMediaList(true);
}

ezyadmin.onSearchMediaLimitChanged = function(e) {
	ezyadmin.numberOfMediaPerPage = $(e).val();
	ezyadmin.fetchMediaList(true);
}

ezyadmin.onMediaDisplayTypeChanged = function(e) {
	ezyadmin.mediaDisplayType = $(e).val();
	ezyadmin.renderMediaList();
}

// ========== media list =============
ezyadmin.mediaCount = 0;
ezyadmin.mediaTotal = 0;
ezyadmin.mediaById = {};
ezyadmin.mediaList = [];
ezyadmin.mediaDisplayType = 'ICONS';

ezyadmin.fetchMediaList = function(replace) {
	var url = ezyadmin.mediaListApiTemp;
	ezyadmin.mediaListApiTemp = null;
	if (!url) {
		url = ezyadmin.accessibleUris['/api/v1/media/list']
			? '/api/v1/media/list'
			: '/api/v1/me/media/list';
	}
	url += '?limit=' + ezyadmin.numberOfMediaPerPage;
	if (ezyadmin.searchMediaKeyword) {
		url += '&keyword=' + ezyadmin.searchMediaKeyword;
	}
	if (ezyadmin.searchMediaGroupNamePrefix) {
		url += '&groupNamePrefix=' + ezyadmin.searchMediaGroupNamePrefix;
	}
	if (ezyadmin.searchMediaType) {
		url += '&type=' + ezyadmin.searchMediaType;
	}
	if (ezyadmin.searchMediaStatus) {
		url += '&status=' + ezyadmin.searchMediaStatus;
	}
	if (ezyadmin.searchMediaCreatedAtStartInclusive) {
		url += '&createdAtStartInclusive=' + ezyadmin.searchMediaCreatedAtStartInclusive;
	}
	if (ezyadmin.searchMediaCreatedAtEndInclusive) {
		url += '&createdAtEndInclusive=' + ezyadmin.searchMediaCreatedAtEndInclusive;
	}
	if (ezyadmin.searchMediaSortOrder) {
		url += '&sortOrder=' + ezyadmin.searchMediaSortOrder;
	}
	if (replace) {
		ezyadmin.mediaById = {};
		ezyadmin.mediaList = [];
		ezyadmin.lastNextPageToken = null;
	}
    $.ajax({
        type: "GET",
        url: url + (ezyadmin.lastNextPageToken
        	? '&nextPageToken=' + ezyadmin.lastNextPageToken
        	: ''),
        success: function(data) {
            data.items.forEach((item) => {
				ezyadmin.mediaById[item.id] = item;
            });
            ezyadmin.mediaList = replace
            	? data.items.slice()
            	: ezyadmin.mediaList.concat(data.items);
            ezyadmin.appendToMediaListTable(data.items, false, replace);
            ezyadmin.mediaCount = replace
            	? data.count
            	: ezyadmin.mediaCount + data.count;
            ezyadmin.mediaTotal = data.total;
            $('#mediaCountText').text(ezyadmin.mediaCount);
            $('#totalMediaText').text(ezyadmin.formatTotalResults(data.total));
            ezyadmin.lastNextPageToken = data.pageToken.next;
            if (data.continuation.hasNext) {
                $('#loadMoreMediaButton').removeClass('d-none');
            } else {
            	$('#loadMoreMediaButton').addClass('d-none');
            }
        },
        error: function(data, e) {
            ezyadmin.processGetApiErrors(data);
        }
    });
}

ezyadmin.appendToMediaListTable = function(mediaList, toHead, replace) {
	if (ezyadmin.mediaDisplayType === 'LIST') {
		ezyadmin.renderMediaList();
		return;
	}
	if (ezyadmin.isMediaDateGroupedSortOrder()) {
		$('#mediaListBody').html(
			ezyadmin.buildMediaListBodyHtml(
				ezyadmin.getMediaListForCurrentSortOrder()
			)
		);
		return;
	}
    var html = ezyadmin.buildMediaListBodyHtml(mediaList);
    var mediaListBody = $('#mediaListBody');
    if (replace) {
    	mediaListBody.html(html);
    } else {
    	mediaListBody.html(toHead ? html + mediaListBody.html() : mediaListBody.html() + html);
    }
}

ezyadmin.renderMediaList = function() {
	$('#mediaListBody').html(
		ezyadmin.buildMediaListBodyHtml(
			ezyadmin.getMediaListForCurrentSortOrder()
		)
	);
	ezyadmin.updateMediaListToggleCheckboxState();
}

ezyadmin.isMediaDateGroupedSortOrder = function() {
	return !ezyadmin.searchMediaSortOrder
		|| ezyadmin.searchMediaSortOrder === 'ID_ASC'
		|| ezyadmin.searchMediaSortOrder === 'ID_DESC';
}

ezyadmin.getMediaListForCurrentSortOrder = function() {
	if (!ezyadmin.searchMediaSortOrder) {
		return ezyadmin.getMediaListSortedByIdDesc();
	}
	if (ezyadmin.searchMediaSortOrder === 'ID_ASC') {
		return ezyadmin.getMediaListSortedByIdAsc();
	}
	if (ezyadmin.searchMediaSortOrder === 'ID_DESC') {
		return ezyadmin.getMediaListSortedByIdDesc();
	}
	return ezyadmin.mediaList.slice();
}

ezyadmin.getMediaListSortedByIdDesc = function() {
	return Object.values(ezyadmin.mediaById)
		.sort((a, b) => b.id - a.id);
}

ezyadmin.getMediaListSortedByIdAsc = function() {
	return Object.values(ezyadmin.mediaById)
		.sort((a, b) => a.id - b.id);
}

ezyadmin.buildMediaListItemHtml = function(media) {
	var replaced = ezyadmin.replacedMediaById[media.id];
	var mediaUrl = ezyadmin.extractMediaUrl(media);
	if (replaced) {
		mediaUrl = ezyadmin.extractMediaUrlAddNowAsVersion(media);
	}
	var internalMedia = ezyadmin.isInternalMediaUrl(mediaUrl);
	var deleteButtonHtml = (media.status != 'REMOVED' && media.status != 'DELETED') || ezyadmin.allowPermanentlyDeleteMedia
		? `<span class="text-danger delete-button" aria-hidden="true" onclick="ezyadmin.onFastDeleteMediaClick(${media.id});">&times;</span>`
		: '';
	return `
			<li id="mediaItem${media.id}" role="button"
				onclick="ezyadmin.showMediaDetails(${media.id});"
				onmouseover="ezyadmin.onMediaMouseOver(this, ${media.id});">
				${media.type === 'IMAGE' || media.type === 'AVATAR' ? `
					<img src="${mediaUrl}" alt="${media.originalName}" class="wh-150px img-thumbnail">
					${deleteButtonHtml}
					<input type="checkbox" name="mediaItemCheckbox" class="media-item-checkbox"
						   ${ezyadmin.isMediaItemChecked(media.id) ? 'checked' : ''}
						   onclick="ezyadmin.onMediaItemCheckboxClick(this, ${media.id})">
				` : (media.type === 'VIDEO' && internalMedia) ? `
					<video class="video-thumbnail">
						<source src="${mediaUrl}" type="video/mp4">
						<source src="${mediaUrl}" type="video/ogg">
						Your browser does not support the video tag.
					</video>
					${deleteButtonHtml}
					<input type="checkbox" name="mediaItemCheckbox" class="media-item-checkbox video-item-checkbox"
						   ${ezyadmin.isMediaItemChecked(media.id) ? 'checked' : ''}
						   onclick="ezyadmin.onMediaItemCheckboxClick(this, ${media.id})">
				` : (media.type === 'AUDIO' && internalMedia) ? `
					<div class="d-flex justify-content-center">
						<div class="file-thumbnail audio-thumbnail">
							<audio controls>
								<source src="${mediaUrl}" type="audio/mpeg">
								<source src="${mediaUrl}" type="audio/ogg">
								Your browser does not support the audio tag.
							</audio>
							<span class="text-dark-always">${media.originalName}</span>
						</div>
						${deleteButtonHtml}
						<input type="checkbox" name="mediaItemCheckbox" class="media-item-checkbox"
							   ${ezyadmin.isMediaItemChecked(media.id) ? 'checked' : ''}
							   onclick="ezyadmin.onMediaItemCheckboxClick(this, ${media.id})">
					</div>
				` : `
					<div class="d-flex justify-content-center">
						<div class="file-thumbnail">
							<i class="far fa-file text-dark-always"></i>
							<div><span class="text-dark-always">${media.originalName}</span></div>
						</div>
						${deleteButtonHtml}
						<input type="checkbox" name="mediaItemCheckbox" class="media-item-checkbox"
							   ${ezyadmin.isMediaItemChecked(media.id) ? 'checked' : ''}
							   onclick="ezyadmin.onMediaItemCheckboxClick(this, ${media.id})">
					</div>
				`}
			</li>`;
}

ezyadmin.buildGroupedMediaListBodyHtml = function(mediaList) {
	var html = '';
	var currentDateKey = '';
	mediaList.forEach((media) => {
		var dateKey = ezyadmin.getMediaCreatedDateKey(media);
		if (dateKey !== currentDateKey) {
			currentDateKey = dateKey;
			html += `
				<li class="text-left font-weight-bold pt-2 pb-1"
					style="grid-column: 1 / -1;">
					${ezyadmin.getMediaCreatedDateLabel(media)}
				</li>`;
		}
		html += ezyadmin.buildMediaListItemHtml(media);
	});
	return html;
}

ezyadmin.buildListGroupedMediaListBodyHtml = function(mediaList) {
	var groups = [];
	var currentGroup = null;
	mediaList.forEach((media) => {
		var dateKey = ezyadmin.getMediaCreatedDateKey(media);
		if (!currentGroup || currentGroup.dateKey !== dateKey) {
			currentGroup = {
				dateKey: dateKey,
				label: ezyadmin.getMediaCreatedDateLabel(media),
				items: []
			};
			groups.push(currentGroup);
		}
		currentGroup.items.push(media);
	});
	var html = '';
	groups.forEach((group, index) => {
		var rowsHtml = group.items
			.map((mediaItem) => ezyadmin.buildListMediaListItemHtml(mediaItem))
			.join('');
		html += `
			<div class="media-list-section">
				<div class="media-list-date-label">${group.label}</div>
				${ezyadmin.buildListMediaTableHtml(rowsHtml, index === 0)}
			</div>`;
	});
	return `<li class="media-list-display-list">${html}</li>`;
}

ezyadmin.buildListTableHtml = function(mediaList) {
	var rowsHtml = mediaList
		.map((mediaItem) => ezyadmin.buildListMediaListItemHtml(mediaItem))
		.join('');
	return `
		<li class="media-list-display-list">
			${ezyadmin.buildListMediaTableHtml(rowsHtml, true)}
		</li>`;
}

ezyadmin.buildListMediaTableHtml = function(rowsHtml, includeHeader) {
	return `
		<div class="media-list-table">
			<table class="table table-hover table-sm">
				<colgroup>
					<col class="media-column">
					<col class="owner-column">
					<col class="type-column">
					<col class="size-column">
					<col class="updated-at-column">
					<col class="action-column">
				</colgroup>
				${includeHeader ? `
					<thead>
						<tr>
							<th>
								<div class="media-list-header-title">
									<input type="checkbox" class="media-list-toggle-checkbox"
										   onclick="ezyadmin.onMediaListToggleCheckboxClick(this);">
									<span>${ezyadmin.messages.name}</span>
								</div>
							</th>
							<th>${ezyadmin.messages.upload_by}</th>
							<th class="text-center">${ezyadmin.messages.type}</th>
							<th class="text-center">${ezyadmin.messages.file_size}</th>
							<th class="text-center">${ezyadmin.messages.updated_at}</th>
							<th class="text-center">${ezyadmin.messages.action}</th>
						</tr>
					</thead>
				` : ''}
				<tbody>
					${rowsHtml}
				</tbody>
			</table>
		</div>`;
}

ezyadmin.buildListMediaListItemHtml = function(media) {
	return `
		<tr id="mediaItem${media.id}" role="button"
			onclick="ezyadmin.showMediaDetails(${media.id});"
			onmouseover="ezyadmin.onMediaMouseOver(this, ${media.id});">
			<td>${ezyadmin.buildListMediaCellHtml(media)}</td>
			<td>${ezyadmin.buildMediaOwnerCellHtml(media)}</td>
			<td class="text-center"><span class="media-list-cell-text">${ezyadmin.getI18nMessage(media.type?.toLowerCase() || '')}</span></td>
			<td class="text-center"><span class="media-list-cell-text">${ezyadmin.toCapacityString(media.size || 0)}</span></td>
			<td class="text-center"><span class="media-list-cell-text">${ezyadmin.formatTimeStamp(media.updatedAt || media.createdAt)}</span></td>
			<td class="text-center">${ezyadmin.buildListMediaActionHtml(media)}</td>
		</tr>`;
}

ezyadmin.buildListMediaCellHtml = function(media) {
	return `
		<div class="media-list-item-title">
			<input type="checkbox" name="mediaItemCheckbox" class="media-item-checkbox"
				   ${ezyadmin.isMediaItemChecked(media.id) ? 'checked' : ''}
				   onclick="ezyadmin.onMediaItemCheckboxClick(this, ${media.id})">
			${ezyadmin.buildListMediaIconHtml(media)}
			<span class="media-list-item-name">${media.originalName || ''}</span>
		</div>`;
}

ezyadmin.buildListMediaIconHtml = function(media) {
	var replaced = ezyadmin.replacedMediaById[media.id];
	var mediaUrl = replaced
		? ezyadmin.extractMediaUrlAddNowAsVersion(media)
		: ezyadmin.extractMediaUrl(media);
	if (media.type === 'IMAGE' || media.type === 'AVATAR') {
		return `
			<span class="media-list-item-icon">
				<img src="${mediaUrl}" alt="${media.originalName || ''}">
			</span>`;
	}
	var iconClass = 'far fa-file';
	if (media.type === 'VIDEO') {
		iconClass = 'fas fa-video';
	} else if (media.type === 'AUDIO') {
		iconClass = 'fas fa-music';
	}
	return `
		<span class="media-list-item-icon">
			<i class="${iconClass} text-dark-always"></i>
		</span>`;
}

ezyadmin.buildMediaOwnerCellHtml = function(media) {
	var ownerHtml = ezyadmin.getMediaOwnerHtml(media);
	if (ownerHtml) {
		return ownerHtml;
	}
	return '<span class="media-list-cell-text muted">-</span>';
}

ezyadmin.buildListMediaActionHtml = function(media) {
	var deleteAble = (media.status != 'REMOVED' && media.status != 'DELETED')
		|| ezyadmin.allowPermanentlyDeleteMedia;
	if (!deleteAble) {
		return '';
	}
	return `
		<button type="button" class="btn btn-link text-danger p-0 media-list-action-button"
			title="${ezyadmin.messages.trash}"
			aria-label="${ezyadmin.messages.trash}"
			onclick="ezyadmin.onFastDeleteMediaClick(${media.id}); event.stopPropagation();">
			<i class="far fa-trash-alt"></i>
		</button>`;
}

ezyadmin.isMediaItemChecked = function(mediaId) {
	return ezyadmin.checkedMediaItemIds.indexOf(mediaId) >= 0;
}

ezyadmin.getMediaOwnerHtml = function(media) {
	if (media.ownerAdmin) {
		var profileUrl = `/admins/${media.ownerAdmin.username}${ezyadmin.lang ? `?lang=${ezyadmin.lang}` : ''}`;
		return `<a class="media-list-cell-text" href="${profileUrl}" onclick="event.stopPropagation();">${media.ownerAdmin.name} (${ezyadmin.messages.administrator.toLowerCase()})</a>`;
	}
	if (media.ownerUser) {
		var profileUrl = `/users/${media.ownerUser.username}${ezyadmin.lang ? `?lang=${ezyadmin.lang}` : ''}`;
		return `<a class="media-list-cell-text" href="${profileUrl}" onclick="event.stopPropagation();">${media.ownerUser.name} (${ezyadmin.messages.user.toLowerCase()})</a>`;
	}
	return '';
}

ezyadmin.getMediaCreatedDateKey = function(media) {
	return ezyadmin.formatTimeStampDate(media.createdAt, 'YYYY-MM-DD');
}

ezyadmin.getMediaCreatedDateLabel = function(media) {
	return ezyadmin.formatTimeStampDate(media.createdAt);
}

ezyadmin.buildMediaListBodyHtml = function(mediaList) {
	if (ezyadmin.mediaDisplayType === 'LIST') {
		return ezyadmin.buildListMediaListBodyHtml(mediaList);
	}
	if (ezyadmin.isMediaDateGroupedSortOrder()) {
		return ezyadmin.buildGroupedMediaListBodyHtml(mediaList);
	}
    var html = '';
    mediaList.forEach((media) => {
        html += ezyadmin.buildMediaListItemHtml(media);
    });
    return html;
}

ezyadmin.buildListMediaListBodyHtml = function(mediaList) {
	if (ezyadmin.isMediaDateGroupedSortOrder()) {
		return ezyadmin.buildListGroupedMediaListBodyHtml(mediaList);
	}
	return ezyadmin.buildListTableHtml(mediaList);
}

$('#loadMoreMediaButton').on('click', (e) => {
    ezyadmin.fetchMediaList();
});

// ======================= media details =============
ezyadmin.selectedMediaId = 0;
ezyadmin.showMediaDetails = function(mediaId) {
    ezyadmin.selectedMediaId = mediaId;
    ezyadmin.fetchMediaDetailsById(mediaId);
}

ezyadmin.showMediaDetailsProxy = function(mediaId) {
	ezyadmin.showMediaDetails(mediaId);
}

ezyadmin.copyMediaUrl = function() {
    ezyadmin.copyToClipboard('updateMediaUrl', true, 'URL');
}

ezyadmin.copyMediaUrlPath = function(elementId) {
    ezyadmin.copyToClipboard(elementId, false, 'URL');
}

ezyadmin.copyEmbedMediaScript = function() {
    ezyadmin.copyToClipboard(
    	'embedMediaScript',
    	true,
    	ezyadmin.messages.script
	);
}

ezyadmin.setMediaUrlPath = function(elementId, url) {
	$(`#${elementId}`).attr('href', url).text(url);
}

ezyadmin.isInternalMediaUrl = function(mediaUrl) {
	return mediaUrl
		&& !mediaUrl.startsWith('http://')
		&& !mediaUrl.startsWith('https://');
}

ezyadmin.isExternalMediaUrl = function(mediaUrl) {
	return mediaUrl
		&& (mediaUrl.startsWith('http://')
		|| mediaUrl.startsWith('https://'));
}

ezyadmin.fetchMediaDetailsById = function(mediaId, replace) {
	var url = ezyadmin.accessibleUris['/api/v1/media/{id}/details']
		? '/api/v1/media/' + mediaId + '/details'
		: '/api/v1/me/media/' + mediaId + '/details';
	$.ajax({
        url: url,
        type: 'GET',
        dataType: 'json'
    })
    .done(function(media) {
        ezyadmin.selectedMedia = media;
		$('#reduceMediaFileSizeArea')
			.addClass('d-none')
			.removeClass('d-flex');
        var uploadedByHtml = '';
		if (media.ownerAdmin) {
			var profileUrl = `/admins/${media.ownerAdmin.username}${ezyadmin.lang ? `?lang=${ezyadmin.lang}` : ''}`;
			uploadedByHtml = `<a href="${profileUrl}">${media.ownerAdmin.name} (${ezyadmin.messages.administrator.toLowerCase()})</a>`;
		} else if (media.ownerUser) {
			var profileUrl = `/users/${media.ownerUser.username}${ezyadmin.lang ? `?lang=${ezyadmin.lang}` : ''}`;
			uploadedByHtml = `<a href="${profileUrl}">${media.ownerUser.name} (${ezyadmin.messages.user.toLowerCase()})</a>`;
		}
		$('#uploadedBy').html(uploadedByHtml);

		var mediaDetailsBodyHtml = '';
		var mediaUrl = replace
			? ezyadmin.extractMediaUrlAddNowAsVersion(media)
			: ezyadmin.extractMediaUrl(media);
		ezyadmin.selectedMedia.url = mediaUrl;
		if (media.type === 'IMAGE' || media.type === 'AVATAR') {
			var previewAlt = media.alternativeText || media.originalName || '';
			mediaDetailsBodyHtml = `
				<a href="${mediaUrl}" class="media-details-preview-link"
					target="_blank" rel="noopener"
					onclick="ezyadmin.openMediaImagePreview(); return false;">
					<img src="${mediaUrl}" alt="${previewAlt}"
						class="img-fluid media-details-preview-image">
					<span class="media-details-preview-badge">
						<i class="fas fa-search-plus"></i>
						<span>${ezyadmin.messages.zoom}</span>
					</span>
				</a>
				<div class="media-details-preview-hint pt-2">
					<span>${ezyadmin.messages.click_to_view_full_screen_and_zoom}</span>
				</div>`;
		} else if (media.type === 'VIDEO') {
			mediaDetailsBodyHtml = `
				<video class="video-details playable-media-item" controls>
					<source src="${mediaUrl}" type="video/mp4">
					<source src="${mediaUrl}" type="video/ogg">
					Your browser does not support the video tag.
				</video>`;
		} else if (media.type === 'AUDIO') {
			mediaDetailsBodyHtml = `
				<div class="file-details audio-details">
					<audio class="playable-media-item" controls>
						<source src="${mediaUrl}" type="audio/mpeg">
						<source src="${mediaUrl}" type="audio/ogg">
						Your browser does not support the audio tag.
					</audio>
					<span class="text-dark-always">${media.originalName}</span>
				</div>`;
		} else {
			mediaDetailsBodyHtml = `
				<div class="file-details">
					<i class="far fa-file text-dark-always"></i>
					<div>
						<a class="text-dark-always" href="${mediaUrl}" target="_blank">${media.originalName}</a>
					</div>
				</div>`;
		}

		var adminRandomUrlPath =
			`${ezyadmin.adminUrl}/api/v1/media/${media.name}`;
		var adminOriginalUrlPath =
			`${ezyadmin.adminUrl}/api/v1/media/${encodeURIComponent(media.originalName)}`;
		var webOriginalUrlPath =
			`${ezyadmin.webUrl}/api/v1/media/${encodeURIComponent(media.originalName)}`;
		var webMediaUrl = ezyadmin.extractMediaUrl(media);
		if (ezyadmin.isInternalMediaUrl(mediaUrl)) {
			webMediaUrl = ezyadmin.webUrl + mediaUrl;
		}
		if (media.type === 'VIDEO') {
			$('#embedMediaScript').val(`
				<iframe width="560" height="315"
					src="${mediaUrl}"
					title="Video player" frameborder="0"
					allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
					allowfullscreen>
				</iframe>`);
			$('#embedMediaScriptArea').removeClass('d-none');
		} else {
			$('#embedMediaScriptArea').addClass('d-none');
		}
		$('#mediaDetailsBody').html(mediaDetailsBodyHtml);
		$('#uploadedOn').text(ezyadmin.formatTimeStamp(media.createdAt));
		$('#mediaDetailsId').text(media.id);
		$('#updateMediaOriginalName').val(media.originalName);
		$('#originalSizeFileRow').addClass('d-none');
		if (media.originalSizeFileName) {
			$('#originalSizeFile')
				.attr('href', `/api/v1/media/${media.originalSizeFileName}`)
				.text(media.originalSizeFileName);
			$('#originalSizeFileRow').removeClass('d-none');
		}
		$('#fileType').text(media.mimeType);
		ezyadmin.setMediaUrlPath('adminOriginalUrlPath', adminOriginalUrlPath);
		ezyadmin.setMediaUrlPath('adminRandomUrlPath', adminRandomUrlPath);
		ezyadmin.setMediaUrlPath('webOriginalUrlPath', webOriginalUrlPath);
		$('#updateMediaUrl').val(webMediaUrl);
		$('#fileSize').text(ezyadmin.toCapacityString(media.size));
		$('#dimension').text(media.width + 'x' + media.height);
		$('#updateMediaType').val(media.type);
		if (ezyadmin.isExternalMediaUrl(mediaUrl)) {
			$('#updateMediaDuration').val(media.durationInMinutes);
			$('#updateMediaDurationWrapper')
				.removeClass('d-none');
			$('#viewExternalMediaButton')
				.attr('href', mediaUrl)
				.removeClass('d-none');
		} else {
			$('#updateMediaDurationWrapper').addClass('d-none');
			$('#viewExternalMediaButton').addClass('d-none');
		}
		$('#updateMediaAlternativeText').val(media.alternativeText);
		$('#updateMediaGroupName').val(media.groupName);
		$('#updateMediaTitle').val(media.title);
		$('#updateMediaCaption').val(media.caption);
		$('#updateMediaDescription').val(media.description);
		$('#updateNotPublicMedia').prop('checked', !media.publicMedia)
		if (ezyadmin.allowPermanentlyDeleteMedia) {
			$('#deleteMediaOnDetailsButton').removeClass('d-none');
		} else {
			$('#deleteMediaOnDetailsButton').addClass('d-none');
		}
		if (media.status === 'REMOVED') {
			$('#restoreMediaButton').removeClass('d-none');
		} else {
			$('#restoreMediaButton').addClass('d-none');
		}
		$('#selectMediaButton').attr('disabled', false);
		var handler = ezyadmin.mediaSelectedHandlers[ezyadmin.currentMediaSelectedCommand];
		if (handler) {
			var showCallback = handler.showCallback;
			if (showCallback) {
				showCallback(ezyadmin.selectedMedia);
			}
		}
		$('#media-details').modal('show');
    })
    .fail(function(e) {
    	ezyadmin.processGetApiErrors(e);
    });
}

// ======================= media update =============
ezyadmin.updateMedia = function() {
	var updateMediaData = ezyadmin.formDataToObject('updateMediaForm');
	if (updateMediaData.url
		&& updateMediaData.url.startsWith(ezyadmin.webUrl)
	) {
		updateMediaData.url = updateMediaData.url
			.slice(ezyadmin.webUrl.length);
	}
	updateMediaData.notPublic = $('#updateNotPublicMedia').prop('checked');
	delete updateMediaData.notPublicMedia;
    if (ezyadmin.isExternalMediaUrl(updateMediaData.url)) {
		updateMediaData.updateDuration = true;
	} else {
		delete updateMediaData.durationInMinutes;
	}
    var url = ezyadmin.accessibleUris['/api/v1/media/{id}/edit']
    	? '/api/v1/media/' + ezyadmin.selectedMediaId
    	: '/api/v1/me/media/' + ezyadmin.selectedMediaId;
    $.ajax({
        type: "PUT",
        url: url,
        contentType: 'application/json',
        data: JSON.stringify(updateMediaData),
        success: function (data) {
        	ezyadmin.hideFormErrors(updateMediaData);
            ezyadmin.shortToast('bg-success', ezyadmin.messages.update_successfully);
            ezyadmin.fetchMediaDetailsById(ezyadmin.selectedMediaId);
            ezyadmin.fetchMediaList(true);
        },
        error: function (e) {
           	ezyadmin.shortToast('bg-danger', ezyadmin.messages.update_failed);
			ezyadmin.processUpdateApiErrors(updateMediaData, e);
        }
    });
}

// ======================= media update =============
ezyadmin.onReplaceMediaClick = function() {
	$('#replaceMediaFileInput').val('');
	$('#replaceMediaFileInput').trigger('click');
}

ezyadmin.replacedMediaById = {};
ezyadmin.replaceMedia = function() {
	var fileInput = $('#replaceMediaFileInput')[0];
	if (!fileInput.files || !fileInput.files.length) {
		return;
	}
	var mediaId = ezyadmin.selectedMediaId;
	var data = new FormData();
	data.append('file', fileInput.files[0]);
	ezyadmin.showLoadingScreen({showPercent: true});
	var url = ezyadmin.accessibleUris['/api/v1/media/{id}/replace']
		? '/api/v1/media/' + mediaId + '/replace'
		: '/api/v1/me/media/' + mediaId + '/replace';
	$.ajax({
		type: "POST",
		enctype: 'multipart/form-data',
		url: url,
		data: data,
		processData: false,
		contentType: false,
		cache: false,
		xhr: function () {
			var xhr = new window.XMLHttpRequest();
			xhr.upload.addEventListener('progress', function(event) {
				if (event.lengthComputable) {
					var percentComplete = Math.round((event.loaded / event.total) * 100);
					ezyadmin.setLoadingScreenPercent(percentComplete);
				}
			});
			return xhr;
		},
		success: function (data) {
			ezyadmin.setLoadingScreenPercent(100);
			ezyadmin.hideLoadingScreen();
			ezyadmin.fetchMediaDetailsById(mediaId, true);
			ezyadmin.replacedMediaById[mediaId] = data;
			ezyadmin.fetchMediaList(true);
		},
		error: function (e) {
			ezyadmin.hideLoadingScreen();
			ezyadmin.shortToast('bg-danger', ezyadmin.messages.update_failed);
		}
	});
}

// ======================= media delete =============
ezyadmin.onFastDeleteMediaClick = function(mediaId) {
	ezyadmin.deleteMedia(mediaId);
	window.event.stopPropagation();
}

ezyadmin.deleteMedia = function(mediaId) {
	var actualMediaId = (mediaId || ezyadmin.selectedMediaId);
	var url = ezyadmin.accessibleUris['/api/v1/media/{id}/delete']
    	? '/api/v1/media/' + actualMediaId
    	: '/api/v1/me/media/' + actualMediaId;
     $.ajax({
        type: "DELETE",
        url: url,
        success: function (data) {
            ezyadmin.shortToast('bg-success', ezyadmin.messages.delete_successfully);
            $('#media-details').modal('hide');
            ezyadmin.mediaList = ezyadmin.mediaList.filter(
            	(item) => item.id !== actualMediaId
            );
            delete ezyadmin.mediaById[actualMediaId];
            $('#mediaItem' + actualMediaId).remove();
            $('#mediaCountText').text(-- ezyadmin.mediaCount);
            $('#totalMediaText').text(-- ezyadmin.mediaTotal);
        },
        error: function (data, e) {
           ezyadmin.shortToast('bg-danger', ezyadmin.messages.delete_failed);
        }
    });
}

// ======================= media restore =============
ezyadmin.restoreMedia = function(mediaId) {
	var actualMediaId = (mediaId || ezyadmin.selectedMediaId);
	var url = ezyadmin.accessibleUris['/api/v1/media/{id}/restore']
    	? '/api/v1/media/' + actualMediaId + '/restore'
    	: '/api/v1/me/media/' + actualMediaId + '/restore';
     $.ajax({
        type: "PUT",
        url: url,
        success: function (data) {
            ezyadmin.shortToast('bg-success', ezyadmin.messages.update_successfully);
            ezyadmin.fetchMediaDetailsById(actualMediaId);
            ezyadmin.fetchMediaList(true);
        },
        error: function (data, e) {
           ezyadmin.shortToast('bg-danger', ezyadmin.messages.update_failed);
        }
    });
}

// ================ media checkbox ===========
ezyadmin.checkedMediaItemIds = [];
ezyadmin.onMediaItemCheckedListeners = [];
ezyadmin.callOnMediaItemCheckedListeners = function() {
	ezyadmin.onMediaItemCheckedListeners.forEach((it) => {
		it(ezyadmin.checkedMediaItemIds);
	});
}

ezyadmin.onMediaItemCheckboxClick = function(e, mediaId) {
	window.event.stopPropagation();
	var checked = $(e).prop('checked');
	ezyadmin.setMediaItemCheckboxChecked(mediaId, checked);
	ezyadmin.callOnMediaItemCheckedListeners();
}

ezyadmin.setMediaItemCheckboxChecked = function(mediaId, checked) {
	if (checked) {
		if (ezyadmin.checkedMediaItemIds.indexOf(mediaId) < 0) {
			ezyadmin.checkedMediaItemIds.push(mediaId);
		}
	} else {
		ezyadmin.removeItemFromList(ezyadmin.checkedMediaItemIds, mediaId);
	}
}

ezyadmin.onMediaListToggleCheckboxClick = function(e) {
	window.event.stopPropagation();
	var checked = $(e).prop('checked');
	ezyadmin.getMediaListForCurrentSortOrder().forEach((media) => {
		ezyadmin.setMediaItemCheckboxChecked(media.id, checked);
	});
	$('.media-item-checkbox').prop('checked', checked);
	ezyadmin.callOnMediaItemCheckedListeners();
}

ezyadmin.updateMediaListToggleCheckboxState = function() {
	var mediaList = ezyadmin.getMediaListForCurrentSortOrder();
	var checkedCount = 0;
	mediaList.forEach((media) => {
		if (ezyadmin.isMediaItemChecked(media.id)) {
			++checkedCount;
		}
	});
	$('.media-list-toggle-checkbox')
		.prop('checked', mediaList.length > 0 && checkedCount === mediaList.length)
		.prop('indeterminate', checkedCount > 0 && checkedCount < mediaList.length);
}

ezyadmin.defaultHandleSelectedMediaIds = function() {
	ezyadmin.selectedMediaList = [];
	ezyadmin.checkedMediaItemIds.forEach((checkedMediaId) => {
		var selectedMedia = ezyadmin.mediaById[checkedMediaId];
		if (selectedMedia) {
			ezyadmin.selectedMediaList.push(selectedMedia);
		}
	});
	var handler = ezyadmin.mediaSelectedHandlers[ezyadmin.currentMediaSelectedCommand];
	if (handler && handler.selectMultipleCallback) {
		handler.selectMultipleCallback(ezyadmin.selectedMediaList);
	} else {
		ezyadmin.selectedMediaList.forEach((checkedMedia) => {
			ezyadmin.selectedMedia = checkedMedia;
			ezyadmin.selectMedia();
		});
	}
	ezyadmin.checkedMediaItemIds = [];
	ezyadmin.selectedMediaList = [];
}

ezyadmin.onSelectMediasButtonClicked = function() {
	if (ezyadmin.handleSelectedMediaIds) {
		ezyadmin.handleSelectedMediaIds(ezyadmin.checkedMediaItemIds);
	} else {
		ezyadmin.defaultHandleSelectedMediaIds();
	}
	ezyadmin.closeMediaModal();
}

// ================ drag drop to add ===========
$(document).ready(function () {
    var mediaListBody = $('#mediaListBody');

    mediaListBody.on('dragover', function (e) {
        e.preventDefault();
        e.stopPropagation();
        $(this).addClass('dragover');
    });

    mediaListBody.on('dragleave', function (e) {
        e.preventDefault();
        e.stopPropagation();
        $(this).removeClass('dragover');
    });

    mediaListBody.on('drop', function (e) {
        e.preventDefault();
        e.stopPropagation();
        $(this).removeClass('dragover');

        var files = e.originalEvent.dataTransfer.files;
        for (var i = 0; i < files.length; i++) {
            ezyadmin.addNewMedia(files[i], false);
        }
    });
});

// ================== hover ===============
$(document).ready(function(){
	$(document).mousedown(function(event) {
		if (event.which === 1) {
			ezyadmin.isMouseDown = true;
		}
	});

	$(document).mouseup(function(event) {
		if (event.which === 1) { // Left mouse button
			ezyadmin.isMouseDown = false;
		}
	});
});
ezyadmin.onMediaMouseOver = function(e, mediaId) {
	if (ezyadmin.isMouseDown) {
		if (ezyadmin.checkedMediaItemIds.indexOf(mediaId) < 0) {
			ezyadmin.checkedMediaItemIds.push(mediaId);
		}
		var checkbox = $(e).find(".media-item-checkbox");
		checkbox.prop("checked", true);
		ezyadmin.callOnMediaItemCheckedListeners();
	}
}

// ================== media zoom ===============
ezyadmin.openMediaImagePreview = async function(mediaId) {
	if (mediaId) {
		ezyadmin.selectedMediaId = mediaId;
		ezyadmin.selectedMedia = ezyadmin.mediaById[mediaId];
	}
	var lightbox = await ezyadmin.ensurePhotoSwipeLightbox();
	ezyadmin.loadAndOpenLightbox(lightbox);
}

ezyadmin.ensurePhotoSwipeLightbox = async function() {
	if (ezyadmin.photoSwipeLightbox) {
		return ezyadmin.photoSwipeLightbox;
	}
	var module = await import(
		'/js/photoswipe-lightbox.esm.min.js'
	);
	var PhotoSwipeLightbox = module.default;
	var lightbox = new PhotoSwipeLightbox({
		showHideAnimationType: 'fade',
		pswpModule: () => import(
			'/js/photoswipe.esm.min.js'
		),
		arrowKeys: true,
		escKey: true,
		returnFocus: true,
		trapFocus: true,
		preloadFirstSlide: true,
		bgOpacity: 0.92,
		spacing: 0.08,
		allowPanToNext: true,
		wheelToZoom: true,
		clickToCloseNonZoomable: false,
		imageClickAction: 'zoom-or-close',
		tapAction: 'toggle-controls',
		doubleTapAction: 'zoom',
		initialZoomLevel: 'fit',
		secondaryZoomLevel: ezyadmin.imageSecondaryZoomLevel || 2,
		maxZoomLevel: 4,
		closeTitle: ezyadmin.messages.close,
		zoomTitle: ezyadmin.messages.zoom,
		arrowPrevTitle: ezyadmin.messages.previous,
		arrowNextTitle: ezyadmin.messages.next,
		indexIndicatorSep: ' / ',
		...ezyadmin.photoSwipeLightboxSettings
	});
	await lightbox.init();
	if (ezyadmin.photoSwipeLightboxDecorator) {
		ezyadmin.photoSwipeLightboxDecorator(lightbox);
	}
	ezyadmin.photoSwipeLightbox = lightbox;
	return lightbox;
}

ezyadmin.loadAndOpenLightbox = function(lightbox) {
	var mediaList = ezyadmin.currentMediaListTemp;
	if (!mediaList || !mediaList.length) {
		mediaList = ezyadmin.getMediaListSortedByIdDesc();
	}
	ezyadmin.currentMediaListTemp = null;
	var items = [];
	var index = 0;
	mediaList.forEach((it) => {
		if (it.type != 'IMAGE' && it.type != 'AVATAR') {
			return;
		}
		it.lighboxItemIndex = index;
		if (ezyadmin.selectedMedia.id == it.id) {
			it.url = ezyadmin.selectedMedia.url;
			ezyadmin.selectedMedia.lighboxItemIndex = index;
		}
		items.push(ezyadmin.mediaToLightboxItem(it));
		++index;
	});
	lightbox.loadAndOpen(
		ezyadmin.selectedMedia.lighboxItemIndex,
		items
	);
}

ezyadmin.mediaToLightboxItem = function(media) {
	var mediaWidth = media.width || (screen.width - 30);
	var mediaHeight = media.height || mediaWidth * 9 / 16;
	return {
		src: ezyadmin.extractMediaUrl(media),
		width: mediaWidth,
		height: mediaHeight,
		alt: media.alternativeText || media.originalName || ''
	};
}

// ======================= reduce media file size =============
ezyadmin.getReduceMediaFileSizeFailedMessage = function() {
	var media = ezyadmin.selectedMedia || {};
	var fileType = media.mimeType || media.type || '';
	return ezyadmin.messages.reduce_file_size_failed_message
		.replace('{0}', fileType);
}

ezyadmin.onReduceMediaFileSizeClick = function() {
	var media = ezyadmin.selectedMedia;
	if (!media || !media.size || media.size <= 1) {
		ezyadmin.showAlert(ezyadmin.getReduceMediaFileSizeFailedMessage());
		return;
	}
	var maxExpectedFileSize = Math.min(
		ezyadmin.maxReducedImageFileSize || media.size,
		media.size
	);
	var expectedFileSize = Math.max(
		1,
		Math.min(maxExpectedFileSize, Math.floor(media.size * 0.8))
	);
	$('#reduceMediaFileSizeRange')
		.attr('min', 1)
		.attr('max', maxExpectedFileSize)
		.attr('step', Math.max(1, Math.floor(maxExpectedFileSize / 100)))
		.val(expectedFileSize);
	ezyadmin.setReduceMediaFileSizeText(expectedFileSize);
	$('#reduceMediaFileSizeArea')
		.removeClass('d-none')
		.addClass('d-flex');
}

ezyadmin.onReduceMediaFileSizeInputChanged = function() {
	ezyadmin.setReduceMediaFileSizeText(
		Number($('#reduceMediaFileSizeRange').val())
	);
}

ezyadmin.setReduceMediaFileSizeText = function(expectedFileSize) {
	$('#reduceMediaFileSizeText').text(
		ezyadmin.toCapacityString(expectedFileSize)
	);
}

ezyadmin.reduceMediaFileSize = function() {
	ezyadmin.doReduceMediaFileSize({
		showLoading: true
	});
}

ezyadmin.reduceMediaFileSizeAsync = async function(options) {
	return new Promise((resolve, reject) => {
		ezyadmin.doReduceMediaFileSize({
			successCallback: resolve,
			errorCallback: reject,
			...options
		});
	});
}

ezyadmin.doReduceMediaFileSize = function(options) {
	var mediaId = options.mediaId || ezyadmin.selectedMediaId;
	var expectedFileSize = options.expectedFileSize
		|| Number($('#reduceMediaFileSizeRange').val());
	if (options.showLoading) {
		ezyadmin.showLoadingScreen();
	}
	var url = ezyadmin.accessibleUris['/api/v1/media/{id}/reduce-file-size']
		? '/api/v1/media/' + mediaId + '/reduce-file-size'
		: '/api/v1/me/media/' + mediaId + '/reduce-file-size';
	$.ajax({
		type: "POST",
		url: url,
		contentType: 'application/json',
		data: JSON.stringify({
			expectedFileSize: expectedFileSize
		}),
		success: function (data) {
			if (options.showLoading) {
				ezyadmin.hideLoadingScreen();
			}
			if (options.successCallback) {
				options.successCallback(data);
				return;
			}
			if (data && data.reduced) {
				ezyadmin.fetchMediaDetailsById(mediaId, true);
				ezyadmin.fetchMediaListAndClearCheckedMediaItems();
			} else {
				ezyadmin.showAlert(ezyadmin.getReduceMediaFileSizeFailedMessage());
			}
		},
		error: function (e) {
			if (options.showLoading) {
				ezyadmin.hideLoadingScreen();
			}
			if (options.errorCallback) {
				options.errorCallback(e);
				ezyadmin.processUpdateApiErrors({}, e);
				return;
			}
			ezyadmin.showAlert(ezyadmin.getReduceMediaFileSizeFailedMessage());
			ezyadmin.processUpdateApiErrors({}, e);
		}
	});
}

// ======================= reduce media file size =============
ezyadmin.changeSelectedMediaCount = function() {
	var count = ezyadmin.checkedMediaItemIds.length;
	$('.selected-media-count-text').text(
		ezyadmin.messages.selected_pcount_medias
			.replace('{0}', ezyadmin.formatNumberWithCommas(count))
	);
	if (count) {
		$('.selected-media-count-text-wrapper').removeClass('d-none');
	} else {
		$('.selected-media-count-text-wrapper').addClass('d-none');
	}
}

ezyadmin.toggleBulkMediaActionButtons = function() {
	var count = ezyadmin.checkedMediaItemIds.length;
	if (count) {
		$('#selectMediasButton').removeClass('d-none');
		$('.reduce-selected-media-files-button-wrapper').removeClass('d-none');
	} else {
		$('#selectMediasButton').addClass('d-none');
		$('.reduce-selected-media-files-button-wrapper').addClass('d-none');
	}
}

ezyadmin.onMediaItemCheckedListeners.push(ezyadmin.changeSelectedMediaCount);
ezyadmin.onMediaItemCheckedListeners.push(ezyadmin.toggleBulkMediaActionButtons);
ezyadmin.onMediaItemCheckedListeners.push(ezyadmin.updateMediaListToggleCheckboxState);

ezyadmin.onReduceSelectedMediaFilesClick = function() {
	$('#reduce-selected-media-files-confirmation-body-content').text(
		ezyadmin
			.messages
			.do_you_want_to_reduce_selected_media_file_size
			.replace('{0}', ezyadmin.checkedMediaItemIds.length)
	);
	$('#reduce-selected-media-files-confirmation').modal('show');
}

ezyadmin.onReduceSelectedMediaFilesPromptConfirmed = async function() {
	$('#reduce-selected-media-files-confirmation').modal('hide');
	var errorMimeTypes = [];
	var successCount = 0;
	var errorCount = 0;
	var totalSelectedMedia = ezyadmin.checkedMediaItemIds.length;
	ezyadmin.showLoadingScreen();
	for(var i = 0; i < totalSelectedMedia; ++i) {
		var reduceFailed = false;
		var mediaId = ezyadmin.checkedMediaItemIds[i];
		var media = ezyadmin.mediaById[mediaId] || {};
		try {
			var result = await ezyadmin.reduceMediaFileSizeAsync({
				mediaId: mediaId,
				expectedFileSize: ezyadmin.maxReducedImageFileSize
			});
			if (result.reduced) {
				++successCount;
			} else if (media.size > ezyadmin.maxReducedImageFileSize) {
				reduceFailed = true;
			}
		} catch(e) {
			reduceFailed = true;
		}
		if (reduceFailed) {
			++errorCount;
			var mimeType = media.mimeType || '';
			if (mimeType && errorMimeTypes.indexOf(mimeType) < 0) {
				errorMimeTypes.push(mimeType);
			}
		}
	}
	ezyadmin.hideLoadingScreen();
	var message = ezyadmin
			.messages.reduced_the_file_size_of_files_summary
			.replace('{0}', successCount)
			.replace('{1}', totalSelectedMedia);
	if (errorCount) {
		message += '. ' + ezyadmin
			.messages.reduce_file_size_failed_message
			.replace('{0}', errorMimeTypes.join(', '));
	}
	ezyadmin.showAlert(message);
	ezyadmin.fetchMediaListAndClearCheckedMediaItems();
}

ezyadmin.fetchMediaListAndClearCheckedMediaItems = function() {
	ezyadmin.checkedMediaItemIds = [];
	$('.media-list-toggle-checkbox').prop('checked', false);
	$('.media-item-checkbox').prop('checked', false);
	ezyadmin.callOnMediaItemCheckedListeners();
	ezyadmin.fetchMediaList(true);
}
</script>
</body>
</html>
