<template>
	<div class="cl-upload-space-inner" @dragover="onDragover" @drop="onDrop">
		<cl-view-group ref="ViewGroup">
			<template #right>
				<div class="cl-upload-space-inner__right">
					<!-- 操作栏 -->
					<div class="cl-upload-space-inner__header">
						<el-button @click="refresh({ page: 1 })">{{ $t('刷新') }}</el-button>

						<div :style="{ margin: '0px 10px' }">
							<cl-upload
								:ref="setRefs('upload')"
								menu="space"
								type="file"
								multiple
								:show-file-list="false"
								:limit="9999"
								:accept="accept"
								@success="onSuccess"
								@upload="onUpload"
							>
								<el-button type="primary">{{ $t('点击上传') }}</el-button>
							</cl-upload>
						</div>

						<template v-if="!selectable">
							<el-button
								type="danger"
								:disabled="selection.length == 0"
								@click="remove()"
								>{{ $t('删除选中文件') }}</el-button
							>
						</template>
					</div>

					<!-- 文件区域 -->
					<el-scrollbar v-loading="loading" class="cl-upload-space-inner__file">
						<!-- 文件列表 -->
						<template v-if="list.length > 0">
							<div
								class="cl-upload-space-inner__file-list"
								:class="{
									'is-mini': browser.isMini
								}"
							>
								<div
									v-for="item in list"
									:key="item.preload || item.url"
									class="cl-upload-space-inner__file-item"
									@click="select(item)"
								>
									<upload-item :item="item" :list="list" @remove="remove" />

									<!-- 已选序号 -->
									<div
										v-show="onIndex(item.id)"
										class="cl-upload-space-inner__file-index"
									>
										<span>{{ onIndex(item.id) }}</span>
									</div>
								</div>
							</div>
						</template>

						<!-- 空态 -->
						<div v-else class="cl-upload-space-inner__file-empty">
							<el-icon class="el-icon--upload">
								<upload-filled />
							</el-icon>
							<p>{{ $t('将文件拖到此处，或点击按钮上传') }}</p>
						</div>
					</el-scrollbar>

					<div class="cl-upload-space-inner__footer cl-pagination">
						<el-pagination
							v-model:current-page="pagination.page"
							:size="browser.isMini ? 'small' : 'default'"
							:total="pagination.total"
							:default-page-size="pagination.size"
							background
							layout="prev, pager, next"
							@current-change="refresh()"
						/>

						<span v-show="!browser.isMini" class="total">{{
							$t('共 {total} 条', { total: pagination.total })
						}}</span>
					</div>
				</div>
			</template>
		</cl-view-group>
	</div>
</template>

<script lang="ts" setup>
defineOptions({
	name: 'cl-upload-space-inner'
});

import { provide, reactive, ref, watch } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { UploadFilled } from '@element-plus/icons-vue';
import { useCool } from '/@/cool';
import { useViewGroup } from '/@/plugins/view';
import UploadItem from '/@/plugins/upload/components/upload-item/index.vue';
import { useI18n } from 'vue-i18n';
import { assign } from 'lodash-es';

const props = defineProps({
	limit: {
		type: Number,
		default: 99
	},
	accept: String,
	selectable: Boolean
});

const emit = defineEmits(['selection-change', 'confirm']);

const { service, browser, refs, setRefs } = useCool();
const { t } = useI18n();

const { ViewGroup } = useViewGroup({
	label: t('分类'),
	title: t('文件列表'),
	service: service.space.type,
	onEdit() {
		return {
			width: '400px',
			props: {
				labelPosition: 'top'
			},
			dialog: {
				controls: ['close']
			},
			items: [
				{
					label: t('名称'),
					prop: 'name',
					value: '',
					required: true,
					component: {
						name: 'el-input',
						props: {
							maxlength: 20,
							clearable: true
						}
					}
				}
			]
		};
	},
	onSelect(item) {
		refresh({
			classifyId: item.id,
			page: 1
		});
	}
});

// 是否加载中
const loading = ref(false);

// 已选列表
const selection = ref<Eps.SpaceInfoEntity[]>([]);

// 文件列表
const list = ref<Eps.SpaceInfoEntity[]>([]);

// 分页信息
const pagination = reactive({
	page: 1,
	size: 20,
	total: 0
});

// 清空选择
function clear() {
	selection.value = [];
}

// 上传成功
function onSuccess<T extends { id: number }>(data: T) {
	service.space.info
		.add({
			classifyId: ViewGroup.value?.selected?.id,
			...data
		})
		.then(res => {
			data.id = res.id;
		})
		.catch(err => {
			ElMessage.error(err.message);
		});
}

// 上传时
function onUpload(data: any) {
	list.value.unshift(data);
}

// 请求参数
const reqParams = {
	page: 1
};

// 刷新列表
async function refresh(params?: any) {
	// 合并参数
	assign(reqParams, {
		type: props.accept?.split('/')[0].replace('*', '') || undefined,
		...pagination,
		...params
	});

	// 加载中
	if (reqParams.page == 1) {
		loading.value = true;
	}

	await service.space.info.page(reqParams).then(res => {
		// 设置分页
		assign(pagination, res.pagination);

		// 设置列表
		list.value = res.list as Eps.SpaceInfoEntity[];
	});

	// 加载完成
	loading.value = false;
}

// 选择
function select(item: Eps.SpaceInfoEntity) {
	const index = selection.value.findIndex(e => e.id === item.id);

	if (index >= 0) {
		selection.value.splice(index, 1);
	} else {
		if (props.limit == 1) {
			selection.value = [item];
		} else {
			if (selection.value.length < props.limit) {
				selection.value.push(item);
			} else {
				ElMessage.warning(t('最多只能选择{limit}个文件', { limit: props.limit }));
			}
		}
	}
}

// 选择序号
function onIndex(id?: number) {
	return selection.value.findIndex(e => e.id === id) + 1;
}

// 删除选中
function remove(item?: Eps.SpaceInfoEntity) {
	// 已选文件 id
	const ids = item ? [item.id] : selection.value.map(e => e.id);

	ElMessageBox.confirm(t('此操作将删除文件, 是否继续?'), t('提示'), {
		type: 'warning'
	})
		.then(() => {
			ElMessage.success(t('删除成功'));

			// 删除文件及选择
			ids.forEach(id => {
				[list.value, selection.value].forEach(list => {
					const index = list.findIndex(e => e.id === id);
					list.splice(index, 1);
				});
			});

			// 删除请求
			service.space.info
				.delete({
					ids
				})
				.catch(err => {
					ElMessage.error(err.message);
				});
		})
		.catch(() => null);
}

// 拖拽
function onDragover(e: DragEvent) {
	e.preventDefault();
}

// 放下
function onDrop(e: DragEvent) {
	e.preventDefault();

	if (e.dataTransfer) {
		// @ts-expect-error
		e.dataTransfer.files.forEach((file: File, index: number) => {
			setTimeout(() => {
				refs.upload.upload(file);
			}, index * 10);
		});
	}
}

// 监听选择
watch(
	selection,
	val => {
		emit('selection-change', val);
	},
	{
		deep: true
	}
);

provide('space', {
	selection,
	refresh,
	loading,
	list
});

defineExpose({
	selection,
	open,
	close,
	clear,
	refresh
});
</script>

<style lang="scss">
.cl-upload-space-inner {
	height: 100%;
	user-select: none;

	&__right {
		height: 100%;
		width: 100%;
	}

	&__header {
		display: flex;
		align-items: center;
		height: 50px;
		padding: 0 10px;
	}

	&__file {
		height: calc(100% - 110px);
		padding: 0 10px;
		box-sizing: border-box;
		position: relative;

		&-item {
			height: 0;
			min-height: 140px;
			min-width: 140px;
			width: calc(12.5% - 10px);
			padding-top: calc(12.5% - 10px);
			margin: 0 10px 10px 0;
			position: relative;
			box-sizing: border-box;
		}

		&-index {
			position: absolute;
			left: 0;
			top: 0;
			height: 100%;
			width: 100%;
			background-color: rgba(0, 0, 0, 0.4);
			border-radius: 5px;
			pointer-events: none;

			span {
				position: absolute;
				right: 5px;
				top: 5px;
				background-color: var(--el-color-success);
				color: #fff;
				display: inline-block;
				height: 20px;
				width: 20px;
				text-align: center;
				line-height: 20px;
				border-radius: 20px;
				font-size: 14px;
			}
		}

		&-list {
			display: flex;
			flex-wrap: wrap;

			&.is-mini {
				.cl-upload-space-inner__file-item {
					width: calc(50% - 10px);
				}
			}
		}

		&-empty {
			display: flex;
			flex-direction: column;
			align-items: center;
			justify-content: center;
			position: absolute;
			top: 0;
			left: 0;
			right: 0;
			bottom: 0;
			margin: auto;
			height: 180px;
			width: 360px;
			max-width: 80%;
			border-radius: 6px;
			border: 1px dashed var(--el-border-color);
			box-sizing: border-box;
			cursor: pointer;

			&:hover {
				border-color: var(--el-color-primary);
			}

			i {
				font-size: 67px;
				color: #c0c4cc;
			}

			p {
				font-size: 14px;
				margin-top: 15px;
				color: #999;
			}
		}
	}

	&__footer {
		height: 60px;
		display: flex;
		flex-wrap: wrap;
		align-items: center;
		justify-content: center;

		.total {
			font-size: 14px;
			margin: 0 10px;
		}
	}
}
</style>
