import {createLogger} from "@gongt/ts-stl-library/debug/create-logger";
import {LOG_LEVEL} from "@gongt/ts-stl-library/debug/levels";
import {MonkeyPatch} from "@gongt/ts-stl-library/pattern/monkey-patch";
import * as React from "react";

export function injectRenderInspect() {
	const hintRender = createLogger(LOG_LEVEL.SILLY, 'render');
	if (hintRender.enabled) {
		hintRender.fn = console.group.bind(console);
		const m = new MonkeyPatch(React.createElement);
		let timeout, times = {};
		const defTimes = {};
		const cb = () => {
			hintRender('render tick: ');
			const dbg = Object.keys(times).filter((k) => times[k]).map(k => [k, times[k]]);
			console.table(dbg);
			Object.assign(times, defTimes);
			console.groupEnd();
			timeout = null;
		};
		const handle = (name: string) => {
			times[name]++;
			if (!timeout) {
				timeout = setTimeout(cb, 0);
			}
		};
		m.argumentsValue((args: any[]) => {
			const Component: any = args[0];
			if (typeof Component !== 'object' && typeof Component !== 'function') {
				handle(Component);
				return args;
			}
			let name = Component.displayname || Component.constructor.displayName || Component.constructor.name || 'unknown';
			if (name === 'Function' && Component.name) {
				name = Component.name;
			}
			defTimes[name] = 0;
			if (!times.hasOwnProperty(name)) {
				times[name] = 0;
			}
			
			handle(Component);
			if (Component.render) {
				if (!Component['___debug']) {
					Component['___debug'] = true;
					const ov = Component.render.bind(Component);
					Component.render = (...args: any[]) => {
						handle(name);
						return ov(...args);
					};
				}
			}
			return args;
		});
		Object.assign(React, <any>{createElement: m.getFunction()});
	}
}
