<template>
	<div class="article-about">
		<div v-if="article">
			<markdown-view class="content" :content="article.data" />
			<p
				class="update-at gray"
				v-text="'最后编辑时间：' + Time.toPassedDateTime(article.updatedAt || article.createdAt)"
			></p>
		</div>
		<div class="spectrum" @click="toggleBGM" v-popup:text="'点击暂停/播放'">
			<canvas ref="canvas" :width="canvasWidth" height="80"></canvas>
		</div>
		<audio ref="player" autoplay>
			<source src="@/assets/media/fragile.mp3" type="audio/mpeg" />
		</audio>
		<p class="survival-time light-gray" v-text="survivalTime"></p>
		<comment
			v-if="SettingMapper.is(SettingKey.ENABLE_COMMENT) && article && article.showComment"
			:bizType="CommentBizType.ARTICLE"
			:bizId="1"
			:titleStickyOffset="49"
			:canComment="article.canComment"
		/>
	</div>
</template>

<script lang="ts" setup>
import { ArticleView, CommentBizType, MarkdownView, SettingKey, SettingMapper, Time } from "timi-web";
import ArticleAPI from "@/api/ArticleAPI";
import { Comment } from "timi-tdesign-pc";

// 文章
const article = ref<ArticleView<any>>();
onMounted(async () => article.value = await ArticleAPI.view(1));

// 运行时间
const survivalTime = ref<string>("网站已运行 ---- 年 --- 天 -- 小时 -- 分钟 -- 秒");
const survivalTimer = ref();
onMounted(async () => {
	const begin = new Date("2017/10/9 22:32:52");
	clearInterval(survivalTimer.value);
	survivalTimer.value = setInterval(() => {
		const r = Time.between(begin);
		survivalTime.value = `网站已运行 ${r.y} 年 ${r.d} 天 ${r.h} 小时 ${r.m.toString().padStart(2, "0")} 分钟 ${r.s.toString().padStart(2, "0")} 秒`;
	}, 1000);
});
onBeforeUnmount(() => clearInterval(survivalTimer.value));

// 音乐
const player = ref<HTMLAudioElement>();
const canvas = ref<HTMLCanvasElement>();
const canvasWidth = ref(480);
const spectrumRender = ref<number>();

const toggleBGM = () => {
	if (player.value) {
		if (player.value.paused) {
			player.value.play();
		} else {
			player.value.pause();
		}
	}
};

const drawSpectrum = () => {
	if (!canvas.value || !player.value) {
		return;
	}
	let ctx: any = new AudioContext();
	const analyser = ctx.createAnalyser();
	const audioSrc = ctx.createMediaElementSource(<HTMLMediaElement>player.value);
	audioSrc.connect(analyser);
	analyser.connect(ctx.destination);

	const cWidth = canvas.value.width,
		meterSize = 7,
		cHeight = canvas.value.height - 2,
		meterWidth = 6,
		capHeight = 2,
		meterNum = 2400 / meterSize,
		capYPositionArray = [];

	ctx = canvas.value.getContext("2d");
	// 渐变
	const gradient = ctx.createLinearGradient(0, 0, 0, 100);
	gradient.addColorStop(1, "#A67D7B");
	gradient.addColorStop(0.5, "#A67D7B");
	gradient.addColorStop(0, "#A67D7B");

	const capStyle = "#A67D7B";
	// 动画
	(function renderFrame() {
		const array = new Uint8Array(analyser.frequencyBinCount);
		analyser.getByteFrequencyData(array);
		const step = Math.round(array.length / meterNum);
		ctx.clearRect(0, 0, cWidth, cHeight);
		for (let i = 0; i < meterNum; i++) {
			const value = array[i * step];
			if (capYPositionArray.length < Math.round(meterNum)) {
				capYPositionArray.push(value);
			}
			ctx.fillStyle = capStyle;
			if (value < capYPositionArray[i]) {
				ctx.fillRect(4 + i * meterSize, cHeight - (--capYPositionArray[i] / 3.2), meterWidth, capHeight);
			} else {
				ctx.fillRect(4 + i * meterSize, cHeight - value / 3.2, meterWidth, capHeight);
				capYPositionArray[i] = value;
			}
			ctx.fillStyle = gradient;
			ctx.fillRect(4 + i * meterSize, cHeight - value / 3.2 + capHeight, meterWidth, cHeight);
		}
		spectrumRender.value = requestAnimationFrame(renderFrame);
	})();
};
onMounted(async () => {
	if (player.value) {
		player.value.volume = .2;
		player.value.addEventListener("loadeddata", () => {
			if (player.value && 2 <= player.value.readyState) {
				// TODO: 成功 play 才允许绘制
				drawSpectrum();
			}
		});
	}
});
onBeforeUnmount(() => {
	if (spectrumRender.value) {
		cancelAnimationFrame(spectrumRender.value);
	}
});
</script>

<style lang="less" scoped>
.article-about {

	.content {
		width: calc(100% - 2rem);
		padding: .5rem 1rem;
	}

	.update-at {
		text-align: right;
		padding-right: 1rem;
	}

	.spectrum {
		width: 20rem;
		height: 320px;
		margin: 0 auto;
		display: flex;
		background: url("@/assets/img/nagiasu.png") bottom no-repeat;
		flex-direction: column;
		justify-content: end;
		background-size: 100%;
	}

	.survival-time {
		height: 16px;
		font-size: 13px;
		text-align: center;
	}
}
</style>
