class Video {
	constructor(id, cpn, attrs) {
		this.id = id;
		this.cpn = cpn;
		this.state = "beforeCreate";
		this.options = {};
		this.attrs = Object.assign(
			{
				src: "",
				controls: true,
				danmuBtn: false,
				enableDanmu: false,
				autoplay: false,
				loop: false,
				muted: false,
				initialTime: 0,
				enableProgressGesture: true,
				playBtnPosition: "bottom",
				objectFit: "contain",
				showMuteBtn: false,
				enablePlayGesture: false,
				vslideGesture: false,
			},
			attrs
		);
		this.actions = {
			playing: false,
			stopped: false,
			progress: 0,
			playbackRate: 1,
		};
		this.styles = {
			x: 0,
			y: 0,
			width: 0,
			height: 0,
			fixed: false,
			hidden: false,
		};
	}

	_setStyles() {
		const cpn = this.cpn;
		const $el = cpn.$el;

		let positionInfo = $el.getBoundingClientRect();
		let styleInfo = window.getComputedStyle($el);
		let isFixed = styleInfo.getPropertyValue("position") === "fixed";
		this.styles = {
			x: isFixed ? positionInfo.left : positionInfo.left + SmallApp.getScrollData('left'),
			y: isFixed ? positionInfo.top : positionInfo.top + SmallApp.getScrollData('top'),
			width: positionInfo.width,
			height: positionInfo.height,
			fixed: isFixed,
			hidden: styleInfo.getPropertyValue("display") === "none",
		};
	}

	create() {
		if (this.state === 'created') {
			return;
		}

		this._setStyles();
		this.state = "created";

        SmallApp.nativeComponent({
          ...this._getBasicData(),
          actionType: "create",
          videoAttr: this.attrs,
          styles: this.styles,
          zIndex: Number(this.cpn.$el.getAttribute('B-zIndex'))
        });
        this.cpn.$emit('oncreated');
    }

	updateAttr(key, value, isPostMessage) {
		const oldValue = this.attrs[key];

		if (oldValue === undefined || oldValue === value) {
			// 设置无效key或value没有变化或video未创建
			return;
		}
		this.attrs[key] = value;

		// 视频没有交点，只改属性，不发送数据
		if (isPostMessage) {
			SmallApp.nativeComponent({
				...this._getBasicData(),
				actionType: "update",
				videoAttr: {
					[key]: value
				}
			});
		}
	}

	updateStyles() {
		if (this.state !== "created") {
			return;
		}

		const cpn = this.cpn;
		const $el = cpn.$el;

		let positionInfo = $el.getBoundingClientRect();
		let styleInfo = window.getComputedStyle($el);
		let isFixed = styleInfo.getPropertyValue("position") === "fixed";
		const newStyles = {
			x: isFixed ? positionInfo.left : positionInfo.left + SmallApp.getScrollData('left'),
			y: isFixed ? positionInfo.top : positionInfo.top + SmallApp.getScrollData('top'),
			width: positionInfo.width,
			height: positionInfo.height,
			fixed: isFixed,
			hidden: styleInfo.getPropertyValue("display") === "none",
		};

		const diffStyles = diffJson(this.styles, newStyles);

		if (diffStyles) {
			this.styles = newStyles;

			SmallApp.nativeComponent({
				...this._getBasicData(),
				actionType: "update",
				styles: diffStyles,
			});
		}
	}

	updateActions(key, value) {
		const oldValue = this.actions[key];

		if (oldValue === undefined || this.state !== "created") {
			// 设置无效key或value没有变化
			return;
		}
		this.actions[key] = value;

		SmallApp.nativeComponent({
			...this._getBasicData(),
			actionType: "update",
			videoAttr: {
				[key]: value
			},
		});
	}

	destroy() {
		this.state = "destroyed";

		SmallApp.nativeComponent({
			...this._getBasicData(true),
			actionType: "destroy",
		});
	}

	play() {
		this.updateActions("playing", true);
	}

	pause() {
		this.updateActions("playing", false);
	}

	stop() {
		this.updateActions("stopped", true);
	}

	seek(second) {
		this.updateActions("progress", second);
	}

	playbackRate(rate) {
		this.updateActions("playbackRate", rate);
	}

	setPlaybackRate(rate) {
		this.playbackRate(rate);
	}

	_getBasicData(isDestroy) {
		return {
			type: "native-component",
			id: this.cpn._uid,
			name: "video",
			destroy: !!isDestroy,
		};
	}
}

export default Video;

function diffJson(oldJson, newJson) {
	if (typeof newJson !== "object" || typeof oldJson !== "object") {
		return newJson;
	}

	let diff = null;
	Object.keys(newJson).forEach((k) => {
		if (oldJson[k] !== newJson[k]) {
			if (!diff) {
				diff = {};
			}

			diff[k] = newJson[k];
		}
	});

	return diff;
}
