import { InfoCard } from "../info_card";
frappe.ui.form.ControlInput = class ControlInput extends frappe.ui.form.Control {
	static horizontal = true;
	make() {
		// parent element
		super.make();
		this.set_input_areas();

		// set description
		this.set_max_width();
		// set initial value if set
		if (this.df.initial_value) {
			this.set_value(this.df.initial_value);
		}
	}
	make_wrapper() {
		if (this.only_input) {
			this.$wrapper = $('<div class="form-group frappe-control">').appendTo(this.parent);
		} else {
			this.$wrapper = $(
				`<div class="frappe-control">
				<div class="form-group">
					<div class="clearfix">
						<label class="control-label" style="padding-right: 5px;"></label>
						<span class="help"></span>
					</div>
					<div class="control-input-wrapper">
						<div class="control-input"></div>
						<div class="control-value like-disabled-input hide"></div>
						<div class="help-box small text-extra-muted hide"></div>
					</div>
				</div>
			</div>`
			).appendTo(this.parent);

			if (this.constructor.horizontal) {
				this.$wrapper.find(".form-group").addClass("horizontal");
			}
		}
	}
	toggle_label(show) {
		this.$wrapper.find(".control-label").parent().toggleClass("hide", !show);
	}
	toggle_description(show) {
		this.$wrapper.find(".help-box").toggleClass("hide", !show);
	}
	set_input_areas() {
		if (this.only_input) {
			this.input_area = this.wrapper;
		} else {
			this.label_area = this.label_span = this.$wrapper.find("label").get(0);
			this.input_area = this.$wrapper.find(".control-input").get(0);
			this.$input_wrapper = this.$wrapper.find(".control-input-wrapper");
			// keep a separate display area to rendered formatted values
			// like links, currencies, HTMLs etc.
			this.disp_area = this.$wrapper.find(".control-value").get(0);
		}
		this.setup_shortcut();
	}
	setup_shortcut() {
		$(this.input_area).on("keydown", function (event) {
			if (event.originalEvent.ctrlKey || event.originalEvent.metaKey) {
				if (event.originalEvent.key === "k" || event.originalEvent.key === "K") {
					$("#navbar-modal-search").click();
					event.preventDefault();
					return false;
				}
			}
		});
	}
	set_max_width() {
		if (this.constructor.horizontal) {
			this.$wrapper.addClass("input-max-width");
		}
	}

	read_only_because_of_fetch_from() {
		return (
			this.df.fetch_from &&
			!this.df.fetch_if_empty &&
			this.frm?.doc?.[this.df.fetch_from.split(".")[0]]
		);
	}

	// update input value, label, description
	// display (show/hide/read-only),
	// mandatory style on refresh
	refresh_input() {
		var me = this;
		var make_input = function () {
			if (!me.has_input) {
				me.make_input();
				if (me.df.on_make) {
					me.df.on_make(me);
				}
			}
		};

		var update_input = function () {
			if (me.doctype && me.docname) {
				me.set_input(me.value);
			} else {
				me.set_input(me.value || null);
			}
		};

		if (me.disp_status != "None") {
			// refresh value
			if (me.frm) {
				me.value = frappe.model.get_value(me.doctype, me.docname, me.df.fieldname);
			} else if (me.doc) {
				me.value = me.doc[me.df.fieldname] || "";
			}

			let is_fetch_from_read_only = me.read_only_because_of_fetch_from();

			if (me.can_write() && !is_fetch_from_read_only) {
				me.disp_area && $(me.disp_area).addClass("hide");
				$(me.input_area).removeClass("hide");
				me.$input && me.$input.prop("disabled", false);
				make_input();
				update_input();
			} else {
				if (me.only_input) {
					make_input();
					update_input();
				} else {
					$(me.input_area).addClass("hide");
					if (me.disp_area) {
						me.set_disp_area(me.value);
						$(me.disp_area).removeClass("hide");
					}
				}
				me.$input && me.$input.prop("disabled", true);

				if (is_fetch_from_read_only) {
					$(me.disp_area).attr(
						"title",
						__(
							"This value is fetched from {0}'s {1} field",
							me.df.fetch_from.split(".").map((value) => __(frappe.unscrub(value)))
						)
					);
				}
			}

			me.set_description();
			me.set_label();
			me.set_doc_url();
			me.set_mandatory(me.value);
			me.set_bold();
			me.set_required();
		}
	}

	can_write() {
		return this.disp_status == "Write";
	}

	set_disp_area(value) {
		if (
			["Currency", "Int", "Float"].includes(this.df.fieldtype) &&
			(this.value === 0 || value === 0)
		) {
			// to set the 0 value in readonly for currency, int, float field
			value = 0;
		} else {
			value = this.value || value;
		}
		if (
			["Data", "Long Text", "Small Text", "Text", "Password", "MultiSelect"].includes(
				this.df.fieldtype
			)
		) {
			value = frappe.utils.escape_html(value);
		}
		let doc = this.doc || (this.frm && this.frm.doc);
		let display_value = frappe.format(value, this.df, { no_icon: true, inline: true }, doc);
		// This is used to display formatted output AND showing values in read only fields
		if (this.disp_area) {
			$(this.disp_area).html(display_value);
			// Apply alignment only for supported fields
			if (
				this.df.alignment &&
				["Data", "Int", "Float", "Currency", "Percent"].includes(this.df.fieldtype)
			) {
				$(this.disp_area).css("text-align", this.df.alignment.toLowerCase());
			}
		}
	}
	set_label(label) {
		const me = this;
		if (label) this.df.label = label;

		if (this.only_input || this.df.label == this._label) return;

		var icon = "";
		this.label_span.innerHTML =
			(icon ? '<i class="' + icon + '"></i> ' : "") +
				__(this.df.label, null, this.df.parent) || "&nbsp;";
		this.show_description_on_click();
		this._label = this.df.label;
	}
	show_description_on_click() {
		const me = this;
		if (this.df.show_description_on_click) {
			let info_card = new InfoCard({
				label_area: this.label_area,
				label_span: this.label_span,
				df: this.df,
			});
		}
	}
	set_doc_url() {
		if (this.df.show_description_on_click) return;
		let unsupported_fieldtypes = frappe.model.no_value_type.filter(
			(x) => frappe.model.table_fields.indexOf(x) === -1
		);
		if (
			!this.df.label ||
			!this.df?.documentation_url ||
			unsupported_fieldtypes.includes(this.df.fieldtype)
		)
			return;

		let $help = this.$wrapper.find("span.help");
		$help.empty();

		$(`<a
			href="${frappe.utils.escape_html(this.df.documentation_url)}"
			target="_blank"
			title="${frappe.utils.escape_html(__("Documentation"))}"
		>
			${frappe.utils.icon("help", "sm")}
		</a>`).appendTo($help);
	}

	set_description(description) {
		if (this.df.show_description_on_click) return;
		if (description !== undefined) {
			this.df.description = description;
		}
		if (this.only_input || this.df.description === this._description) {
			return;
		}
		if (this.df.description) {
			const description = __(this.df.description, null, this.df.parent);
			const help_box = this.$wrapper.find(".help-box");
			help_box.html(description);
			if (description.includes("<code")) {
				frappe.require("syntax_highlighting.bundle.js").then(() => {
					help_box.find("code").each(function () {
						hljs.highlightElement(this);
						this.style.display = "inline"; // override hljs's "block" display
					});
				});
			}
			this.toggle_description(true);
		} else {
			this.set_empty_description();
		}
		this._description = this.df.description;
	}
	set_new_description(description) {
		this.$wrapper.find(".help-box").html(description);
		this.toggle_description(true);
	}
	set_empty_description() {
		this.$wrapper.find(".help-box").html("");
		this.toggle_description(false);
	}
	set_mandatory(value) {
		// do not set has-error class on form load
		if (this.frm && this.frm.cscript && this.frm.cscript.is_onload) return;

		// do not set has-error class while dialog is rendered
		// set has-error if dialog primary button is clicked
		if (this.layout && this.layout.is_dialog && !this.layout.primary_action_fulfilled) return;

		const is_invalid = this.$wrapper.hasClass("has-error-invalid");
		this.$wrapper.toggleClass("has-error-mandatory", Boolean(this.df.reqd && is_null(value)));
		this.$wrapper.toggleClass(
			"has-error",
			is_invalid || Boolean(this.df.reqd && is_null(value))
		);
	}
	set_invalid() {
		let invalid = !!this.df.invalid;
		if (this.grid) {
			this.$wrapper.parents(".grid-static-col").toggleClass("invalid", invalid);
			this.$input?.toggleClass("invalid", invalid);
			this.grid_row.columns[this.df.fieldname].is_invalid = invalid;
		} else {
			const is_mandatory_and_empty = this.$wrapper.hasClass("has-error-mandatory");
			this.$wrapper.toggleClass("has-error-invalid", invalid);
			this.$wrapper.toggleClass("has-error", is_mandatory_and_empty || invalid);
		}
	}
	set_required() {
		this.label_area && $(this.label_area).toggleClass("reqd", Boolean(this.df.reqd));
	}
	set_bold() {
		if (this.$input) {
			this.$input.toggleClass("bold", !!(this.df.bold || this.df.reqd));
		}
		if (this.disp_area) {
			$(this.disp_area).toggleClass("bold", !!(this.df.bold || this.df.reqd));
		}
	}
};
