/** @import { Blocker } from '#client' */
import { dev_current_component_function } from './context.js';
import { FILENAME } from '../../constants.js';
import { render_effect } from './reactivity/effects.js';
import * as w from './warnings.js';
import { capture_store_binding } from './reactivity/store.js';
import { run_after_blockers } from './reactivity/async.js';

/**
 * @param {string} binding
 * @param {Blocker[]} blockers
 * @param {() => Record<string, any>} get_object
 * @param {() => string} get_property
 * @param {number} line
 * @param {number} column
 */
export function validate_binding(binding, blockers, get_object, get_property, line, column) {
	run_after_blockers(blockers, () => {
		var warned = false;

		var filename = dev_current_component_function?.[FILENAME];

		render_effect(() => {
			if (warned) return;

			var [object, is_store_sub] = capture_store_binding(get_object);

			if (is_store_sub) return;

			var property = get_property();

			var ran = false;

			// by making the (possibly false, but it would be an extreme edge case) assumption
			// that a getter has a corresponding setter, we can determine if a property is
			// reactive by seeing if this effect has dependencies
			var effect = render_effect(() => {
				if (ran) return;

				// eslint-disable-next-line @typescript-eslint/no-unused-expressions
				object[property];
			});

			ran = true;

			if (effect.deps === null) {
				var location = `${filename}:${line}:${column}`;
				w.binding_property_non_reactive(binding, location);

				warned = true;
			}
		});
	});
}
