import './style.scss';

import { Component } from '@wordpress/element';

const { navigator } = window;

// generate dom tree.
function getNodeTree(node) {
	if (node && node.hasChildNodes()) {
		const children = [];

		for (let j = 0; j < node.childNodes.length; j += 1) {
			children.push(getNodeTree(node.childNodes[j]));
		}

		return {
			classList: node.classList,
			nodeName: node.nodeName,
			children,
		};
	}

	return false;
}

/**
 * Component Class
 */
export default class ClassesTree extends Component {
	constructor(...args) {
		super(...args);

		this.state = {
			nodes: false,
		};

		this.onFrameLoad = this.onFrameLoad.bind(this);
		this.maybeFindIframe = this.maybeFindIframe.bind(this);
		this.updateTreeData = this.updateTreeData.bind(this);
	}

	componentDidMount() {
		this.maybeFindIframe();
	}

	componentDidUpdate() {
		this.maybeFindIframe();
	}

	componentWillUnmount() {
		if (!this.iframePreview) {
			return;
		}

		this.iframePreview.removeEventListener('load', this.onFrameLoad);
	}

	/**
	 * On frame load event.
	 */
	onFrameLoad() {
		if (!this.iframePreview.contentWindow) {
			return;
		}

		// this.frameWindow = this.iframePreview.contentWindow;
		this.frameJQuery = this.iframePreview.contentWindow.jQuery;

		if (this.frameJQuery) {
			this.$framePortfolio = this.frameJQuery('.vp-portfolio');
		}

		this.updateTreeData();
	}

	maybeFindIframe() {
		if (this.iframePreview) {
			return;
		}

		const { clientId } = this.props;

		const iframePreview = document.querySelector(
			`#block-${clientId} iframe`
		);

		if (iframePreview) {
			this.iframePreview = iframePreview;
			this.iframePreview.addEventListener('load', this.onFrameLoad);
			this.onFrameLoad();
		}
	}

	updateTreeData() {
		if (this.$framePortfolio) {
			this.setState({
				nodes: getNodeTree(this.$framePortfolio[0]),
			});
		}
	}

	render() {
		if (!this.iframePreview) {
			return null;
		}

		return (
			<div className="vpf-component-classes-tree">
				<ClassesTree.TreeItem
					node={this.state.nodes}
					skipNodeByClass={/vp-portfolio__item-popup/}
					collapseByClass={
						/^(vp-portfolio__preloader-wrap|vp-portfolio__filter-wrap|vp-portfolio__sort-wrap|vp-portfolio__items-wrap|vp-portfolio__pagination-wrap)$/
					}
					skipClass={/vp-uid-/}
				/>
			</div>
		);
	}
}

ClassesTree.TreeItem = class TreeItem extends Component {
	constructor(...args) {
		super(...args);

		this.state = {
			isCollapsed: null,
		};

		this.isCollapsed = this.isCollapsed.bind(this);
	}

	isCollapsed() {
		const { node, collapseByClass } = this.props;

		let { isCollapsed } = this.state;

		// check if collapsed by default.
		if (
			isCollapsed === null &&
			node &&
			node.classList &&
			node.classList.length
		) {
			node.classList.forEach((className) => {
				if (collapseByClass && collapseByClass.test(className)) {
					isCollapsed = true;
				}
			});
		}

		return isCollapsed;
	}

	render() {
		const { node, skipNodeByClass, skipClass } = this.props;

		if (!node || !node.children.length) {
			return null;
		}

		const classes = [];
		let skip = false;

		// Classes.
		if (node.classList && node.classList.length) {
			node.classList.forEach((className) => {
				if (!skipClass || !skipClass.test(className)) {
					classes.push(className);
				}

				// Skip?
				if (skipNodeByClass && skipNodeByClass.test(className)) {
					skip = true;
				}
			});
		}

		if (skip) {
			return null;
		}

		return (
			<ul>
				<li
					className={`vpf-component-classes-tree-node ${
						this.isCollapsed() ? '' : 'is-collapsed'
					}`}
				>
					<div>
						{node.children.length ? (
							<button
								type="button"
								className="vpf-component-classes-tree-node-collapse"
								onClick={() =>
									this.setState({
										isCollapsed: !this.isCollapsed(),
									})
								}
							/>
						) : (
							''
						)}
						&lt;
						{node.nodeName.toLowerCase()}
						{classes.length ? (
							<>
								{' class="'}
								{classes.map((className) => (
									<button
										key={className}
										type="button"
										className="vpf-component-classes-tree-node-class"
										onClick={() => {
											navigator.clipboard.writeText(
												className
											);
										}}
									>
										{className}
									</button>
								))}
								{'" '}
							</>
						) : (
							''
						)}
						&gt;
					</div>
				</li>
				{node.children.length && this.isCollapsed()
					? node.children.map((childNode) => {
							if (childNode) {
								return (
									// eslint-disable-next-line react/jsx-key
									<li className="vpf-component-classes-tree-child">
										<ClassesTree.TreeItem
											{...this.props}
											node={childNode}
										/>
									</li>
								);
							}
							return null;
						})
					: ''}
			</ul>
		);
	}
};
