// Copyright (c) 2020, JINGROW and Contributors
// MIT License. See license.txt
import BaseTimeline from "./base_timeline";
import {
	get_version_timeline_content,
	get_user_link,
	get_user_message,
} from "./version_timeline_content_builder";

class FormTimeline extends BaseTimeline {
	make() {
		super.make();
		this.setup_timeline_actions();
		this.render_timeline_items();
		this.setup_activity_toggle();
	}

	refresh() {
		super.refresh();
		this.frm.trigger("timeline_refresh");
		this.setup_document_email_link();
	}

	setup_timeline_actions() {
		if (jingrow.model.can_email(null, this.frm)) {
			this.add_action_button(
				__("New Email"),
				() => this.compose_mail(),
				"es-line-add",
				"btn-secondary"
			);
		}
		this.setup_new_event_button();
	}

	setup_new_event_button() {
		if (this.frm.meta.allow_events_in_timeline) {
			let create_event = () => {
				const args = {
					pg: this.frm.pg,
					frm: this.frm,
					recipients: this.get_recipient(),
					txt: jingrow.markdown(this.frm.comment_box.get_value()),
				};
				return new jingrow.views.InteractionComposer(args);
			};
			this.add_action_button(__("New Event"), create_event, "calendar");
		}
	}

	setup_activity_toggle() {
		let pg_info = this.pg_info || this.frm.get_pageinfo();
		let has_communications = () => {
			let communications = pg_info.communications;
			let comments = pg_info.comments;
			return (communications || []).length || (comments || []).length;
		};
		let me = this;
		this.timeline_wrapper.remove(this.timeline_actions_wrapper);
		this.timeline_wrapper.prepend(`
				<div class="timeline-item activity-title">
				<h4>${__("Activity")}</h4>
				</div>
			`);
		if (has_communications()) {
			this.timeline_wrapper
				.find(".timeline-item.activity-title")
				.append(
					`
					<div class="d-flex align-items-center show-all-activity">
						<span style="color: var(--text-light); margin:0px 6px;">${__("Show all activity")}</span>
						<label class="switch">
							<input type="checkbox">
							<span class="slider round"></span>
						</label>
					</div>
				`
				)
				.find("input[type=checkbox]")
				.prop("checked", !me.only_communication)
				.on("click", function (e) {
					me.only_communication = !this.checked;
					me.render_timeline_items();
					$(this).tab("show");
				});
		}
		this.timeline_wrapper
			.find(".timeline-item.activity-title")
			.append(this.timeline_actions_wrapper);
	}

	setup_document_email_link() {
		let pg_info = this.pg_info || this.frm.get_pageinfo();

		this.document_email_link_wrapper && this.document_email_link_wrapper.remove();

		if (pg_info.document_email) {
			const link = `<a class="document-email-link">${pg_info.document_email}</a>`;
			const message = __("Add to this activity by mailing to {0}", [link.bold()]);

			this.document_email_link_wrapper = $(`
				<div class="timeline-item">
					<div class="timeline-dot"></div>
					<div class="timeline-content">
						<span>${message}</span>
					</div>
				</div>
			`);
			this.timeline_items_wrapper.before(this.document_email_link_wrapper);

			this.document_email_link_wrapper.find(".document-email-link").on("click", (e) => {
				let text = $(e.target).text();
				jingrow.utils.copy_to_clipboard(text);
			});
		}
	}

	render_timeline_items() {
		super.render_timeline_items();
		this.add_web_page_view_count();
		jingrow.utils.bind_actions_with_object(this.timeline_items_wrapper, this);
	}

	add_web_page_view_count() {
		if (this.frm.pg.route && cint(jingrow.boot.website_tracking_enabled)) {
			jingrow.utils.get_page_view_count(this.frm.pg.route).then((res) => {
				this.add_timeline_item({
					content: __("{0} Web page views", [res.message]),
					hide_timestamp: true,
				});
			});
		}
	}

	get_creation_message() {
		return {
			creation: this.frm.pg.creation,
			content: get_user_message(
				this.frm.pg.owner,
				__("You created this"),
				__("{0} created this", [get_user_link(this.frm.pg.owner)])
			),
		};
	}

	get_modified_message() {
		return {
			creation: this.frm.pg.modified,
			content: get_user_message(
				this.frm.pg.modified_by,
				__("You last edited this"),
				__("{0} last edited this", [get_user_link(this.frm.pg.modified_by)])
			),
		};
	}

	prepare_timeline_contents() {
		this.timeline_items.push(this.get_creation_message());
		this.timeline_items.push(this.get_modified_message());
		this.timeline_items.push(...this.get_communication_timeline_contents());
		this.timeline_items.push(...this.get_comment_timeline_contents());
		if (!this.only_communication) {
			this.timeline_items.push(...this.get_view_timeline_contents());
			this.timeline_items.push(...this.get_energy_point_timeline_contents());
			this.timeline_items.push(...this.get_version_timeline_contents());
			this.timeline_items.push(...this.get_share_timeline_contents());
			this.timeline_items.push(...this.get_workflow_timeline_contents());
			this.timeline_items.push(...this.get_like_timeline_contents());
			this.timeline_items.push(...this.get_custom_timeline_contents());
			this.timeline_items.push(...this.get_assignment_timeline_contents());
			this.timeline_items.push(...this.get_attachment_timeline_contents());
			this.timeline_items.push(...this.get_info_timeline_contents());
			this.timeline_items.push(...this.get_milestone_timeline_contents());
		}
	}

	get_view_timeline_contents() {
		let view_timeline_contents = [];
		(this.pg_info.views || []).forEach((view) => {
			view_timeline_contents.push({
				creation: view.creation,
				content: get_user_message(
					view.owner,
					__("You viewed this"),
					__("{0} viewed this", [get_user_link(view.owner)])
				),
			});
		});

		return view_timeline_contents;
	}

	get_communication_timeline_contents(more_communications, more_automated_messages) {
		let email_communications =
			this.get_email_communication_timeline_contents(more_communications);
		let automated_messages = this.get_auto_messages_timeline_contents(more_automated_messages);
		let all_communications = email_communications.concat(automated_messages);

		if (all_communications.length > 20) {
			all_communications.pop();

			if (more_communications || more_automated_messages) {
				all_communications.forEach((message) => {
					if (message.communication_type == "Automated Message") {
						this.pg_info.automated_messages.push(message);
					} else {
						this.pg_info.communications.push(message);
					}
				});
			}

			let last_communication_time =
				all_communications[all_communications.length - 1].creation;
			let load_more_button = {
				creation: last_communication_time,
				content: __("Load More Communications", null, "Form timeline"),
				name: "load-more",
			};
			all_communications.push(load_more_button);
		}

		return all_communications;
	}

	get_email_communication_timeline_contents(more_items) {
		let communication_timeline_contents = [];
		let icon_set = {
			Email: "mail",
			Phone: "call",
			Meeting: "calendar",
			Other: "dot-horizontal",
		};
		let items = more_items ? more_items : this.pg_info.communications || [];
		items.forEach((communication) => {
			let medium = communication.communication_medium;
			communication_timeline_contents.push({
				icon: icon_set[medium],
				icon_size: "sm",
				creation: communication.communication_date,
				is_card: true,
				content: this.get_communication_timeline_content(communication),
				pagetype: "Communication",
				id: `communication-${communication.name}`,
				name: communication.name,
			});
		});

		return communication_timeline_contents;
	}

	async get_more_communication_timeline_contents() {
		let more_items = [];
		let start =
			this.pg_info.communications.length + this.pg_info.automated_messages.length - 1;
		let response = await jingrow.call({
			method: "jingrow.desk.form.load.get_communications",
			args: {
				pagetype: this.pg_info.pagetype,
				name: this.pg_info.name,
				start: start,
				limit: 21,
			},
		});
		if (response.message) {
			let email_communications = [];
			let automated_messages = [];
			response.message.forEach((message) => {
				if (message.communication_type == "Automated Message") {
					automated_messages.push(message);
				} else {
					email_communications.push(message);
				}
			});
			more_items = this.get_communication_timeline_contents(
				email_communications,
				automated_messages
			);
		}
		return more_items;
	}

	get_communication_timeline_content(pg, allow_reply = true) {
		pg._url = jingrow.utils.get_form_link("Communication", pg.name);
		this.set_communication_pg_status(pg);
		if (pg.attachments && typeof pg.attachments === "string") {
			pg.attachments = JSON.parse(pg.attachments);
		}
		pg.owner = pg.sender;
		pg.user_full_name = pg.sender_full_name;
		pg.content = jingrow.dom.remove_script_and_style(pg.content);
		let communication_content = $(jingrow.render_template("timeline_message_box", { pg }));
		if (allow_reply) {
			this.setup_reply(communication_content, pg);
		}
		return communication_content;
	}

	set_communication_pg_status(pg) {
		let indicator_color = "red";
		if (["Sent", "Clicked"].includes(pg.delivery_status)) {
			indicator_color = "green";
		} else if (["Sending", "Scheduled"].includes(pg.delivery_status)) {
			indicator_color = "orange";
		} else if (["Opened", "Read"].includes(pg.delivery_status)) {
			indicator_color = "blue";
		} else if (pg.delivery_status == "Error") {
			indicator_color = "red";
		}
		pg._pg_status = pg.delivery_status;
		pg._pg_status_indicator = indicator_color;
	}

	get_auto_messages_timeline_contents(more_items) {
		let auto_messages_timeline_contents = [];
		let items = more_items ? more_items : this.pg_info.automated_messages || [];
		items.forEach((message) => {
			auto_messages_timeline_contents.push({
				icon: "notification",
				icon_size: "sm",
				creation: message.creation,
				is_card: true,
				content: this.get_communication_timeline_content(message, false),
				pagetype: "Communication",
				name: message.name,
			});
		});
		return auto_messages_timeline_contents;
	}

	get_comment_timeline_contents() {
		let comment_timeline_contents = [];
		(this.pg_info.comments || []).forEach((comment) => {
			comment_timeline_contents.push(this.get_comment_timeline_item(comment));
		});
		return comment_timeline_contents;
	}

	get_comment_timeline_item(comment) {
		return {
			icon: "es-line-chat-alt",
			icon_size: "sm",
			creation: comment.creation,
			is_card: true,
			pagetype: "Comment",
			id: `comment-${comment.name}`,
			name: comment.name,
			content: this.get_comment_timeline_content(comment),
		};
	}

	get_comment_timeline_content(pg) {
		pg.content = jingrow.dom.remove_script_and_style(pg.content);
		const comment_content = $(jingrow.render_template("timeline_message_box", { pg }));
		this.setup_comment_actions(comment_content, pg);
		return comment_content;
	}

	get_version_timeline_contents() {
		let version_timeline_contents = [];
		(this.pg_info.versions || []).forEach((version) => {
			const contents = get_version_timeline_content(version, this.frm);
			contents.forEach((content) => {
				version_timeline_contents.push({
					creation: version.creation,
					content: content,
				});
			});
		});
		return version_timeline_contents;
	}

	get_share_timeline_contents() {
		let share_timeline_contents = [];
		(this.pg_info.share_logs || []).forEach((share_log) => {
			share_timeline_contents.push({
				creation: share_log.creation,
				content: share_log.content,
			});
		});
		return share_timeline_contents;
	}

	get_assignment_timeline_contents() {
		let assignment_timeline_contents = [];
		(this.pg_info.assignment_logs || []).forEach((assignment_log) => {
			assignment_timeline_contents.push({
				creation: assignment_log.creation,
				content: assignment_log.content,
			});
		});
		return assignment_timeline_contents;
	}

	get_info_timeline_contents() {
		let info_timeline_contents = [];
		(this.pg_info.info_logs || []).forEach((info_log) => {
			info_timeline_contents.push({
				creation: info_log.creation,
				content: `${get_user_link(info_log.owner)} ${info_log.content}`,
			});
		});
		return info_timeline_contents;
	}

	get_attachment_timeline_contents() {
		let attachment_timeline_contents = [];

		(this.pg_info.attachment_logs || []).forEach((attachment_log) => {
			const is_file_upload = attachment_log.comment_type == "Attachment";
			const user_link = get_user_link(attachment_log.owner);
			const filename = attachment_log.content;
			const timeline_content = is_file_upload
				? get_user_message(
						attachment_log.owner,
						__("You attached {0}", [filename], "Form timeline"),
						__("{0} attached {1}", [user_link, filename], "Form timeline")
				  )
				: get_user_message(
						attachment_log.owner,
						__("You removed attachment {0}", [filename], "Form timeline"),
						__("{0} removed attachment {1}", [user_link, filename], "Form timeline")
				  );

			attachment_timeline_contents.push({
				icon: is_file_upload ? "es-line-attachment" : "es-line-delete",
				icon_size: "sm",
				creation: attachment_log.creation,
				content: timeline_content,
			});
		});

		return attachment_timeline_contents;
	}

	get_milestone_timeline_contents() {
		let milestone_timeline_contents = [];

		(this.pg_info.milestones || []).forEach((milestone_log) => {
			const field = jingrow.meta.get_label(this.frm.pagetype, milestone_log.track_field);
			const value = milestone_log.value.bold();
			const user_link = get_user_link(milestone_log.owner);
			const timeline_content = get_user_message(
				milestone_log.owner,
				__("You changed {0} to {1}", [field, value], "Form timeline"),
				__("{0} changed {1} to {2}", [user_link, field, value], "Form timeline")
			);

			milestone_timeline_contents.push({
				icon: "milestone",
				creation: milestone_log.creation,
				content: timeline_content,
			});
		});

		return milestone_timeline_contents;
	}

	get_like_timeline_contents() {
		let like_timeline_contents = [];

		(this.pg_info.like_logs || []).forEach((like_log) => {
			const timeline_content = get_user_message(
				like_log.owner,
				__("You Liked"),
				__("{0} Liked", [get_user_link(like_log.owner)])
			);

			like_timeline_contents.push({
				icon: "es-line-like",
				icon_size: "sm",
				creation: like_log.creation,
				content: timeline_content,
				title: "Like",
			});
		});

		return like_timeline_contents;
	}

	get_workflow_timeline_contents() {
		let workflow_timeline_contents = [];
		(this.pg_info.workflow_logs || []).forEach((workflow_log) => {
			workflow_timeline_contents.push({
				icon: "branch",
				icon_size: "sm",
				creation: workflow_log.creation,
				content: `${get_user_link(workflow_log.owner)} ${__(workflow_log.content)}`,
				title: "Workflow",
			});
		});
		return workflow_timeline_contents;
	}

	get_custom_timeline_contents() {
		let custom_timeline_contents = [];
		(this.pg_info.additional_timeline_content || []).forEach((custom_item) => {
			custom_timeline_contents.push({
				icon: custom_item.icon,
				icon_size: "sm",
				is_card: custom_item.is_card,
				creation: custom_item.creation,
				content:
					custom_item.content ||
					jingrow.render_template(custom_item.template, custom_item.template_data),
			});
		});
		return custom_timeline_contents;
	}

	get_energy_point_timeline_contents() {
		let energy_point_timeline_contents = [];
		(this.pg_info.energy_point_logs || []).forEach((log) => {
			let timeline_badge = `
			<div class="timeline-badge ${log.points > 0 ? "appreciation" : "criticism"} bold">
				${log.points}
			</div>`;

			energy_point_timeline_contents.push({
				timeline_badge: timeline_badge,
				creation: log.creation,
				content: jingrow.energy_points.format_form_log(log),
			});
		});
		return energy_point_timeline_contents;
	}

	setup_reply(communication_box, communication_pg) {
		let actions = communication_box.find(".custom-actions");
		let reply = $(`<a class="action-btn reply">${jingrow.utils.icon("reply", "md")}</a>`).click(
			() => {
				this.compose_mail(communication_pg);
			}
		);
		let reply_all = $(
			`<a class="action-btn reply-all">${jingrow.utils.icon("reply-all", "md")}</a>`
		).click(() => {
			this.compose_mail(communication_pg, true);
		});
		actions.append(reply);
		actions.append(reply_all);
	}

	compose_mail(communication_pg = null, reply_all = false) {
		const args = {
			pg: this.frm.pg,
			frm: this.frm,
			recipients:
				communication_pg && communication_pg.sender != jingrow.session.user_email
					? communication_pg.sender
					: this.get_recipient(),
			is_a_reply: Boolean(communication_pg),
			title: communication_pg ? __("Reply") : null,
			last_email: communication_pg,
			subject: communication_pg && communication_pg.subject,
			reply_all: reply_all,
		};

		const email_accounts = jingrow.boot.email_accounts
			.filter((account) => {
				return (
					!["All Accounts", "Sent", "Spam", "Trash"].includes(account.email_account) &&
					account.enable_outgoing
				);
			})
			.map((e) => e.email_id);

		if (communication_pg && args.is_a_reply) {
			args.cc = "";
			if (
				email_accounts.includes(jingrow.session.user_email) &&
				communication_pg.sender != jingrow.session.user_email
			) {
				// add recipients to cc if replying sender is different from last email
				const recipients = communication_pg.recipients.split(",").map((r) => r.trim());
				args.cc =
					recipients.filter((r) => r != jingrow.session.user_email).join(", ") + ", ";
			}
			if (reply_all) {
				// if reply_all then add cc and bcc as well.
				args.cc += cstr(communication_pg.cc);
				args.bcc = cstr(communication_pg.bcc);
			}
		}

		if (this.frm.pagetype === "Communication") {
			args.message = "";
			args.last_email = this.frm.pg;
			args.recipients = this.frm.pg.sender;
			args.subject = __("Re: {0}", [this.frm.pg.subject]);
		} else {
			const comment_value = jingrow.markdown(this.frm.comment_box.get_value());
			args.message = strip_html(comment_value) ? comment_value : "";
		}

		new jingrow.views.CommunicationComposer(args);
	}

	get_recipient() {
		if (this.frm.email_field) {
			return this.frm.pg[this.frm.email_field];
		} else {
			return this.frm.pg.email_id || this.frm.pg.email || "";
		}
	}

	setup_comment_actions(comment_wrapper, pg) {
		let edit_wrapper = $(`<div class="comment-edit-box">`).hide();
		let edit_box = this.make_editable(edit_wrapper);
		let content_wrapper = comment_wrapper.find(".content");
		let more_actions_wrapper = comment_wrapper.find(".more-actions");
		if (
			jingrow.model.can_delete("Comment") &&
			(jingrow.session.user == pg.owner || jingrow.user.has_role("System Manager"))
		) {
			const delete_option = $(`
				<li>
					<a class="dropdown-item">
						${__("Delete")}
					</a>
				</li>
			`).click(() => this.delete_comment(pg.name));
			more_actions_wrapper.find(".dropdown-menu").append(delete_option);
		}

		let dismiss_button = $(`
			<button class="btn btn-link action-btn">
				${__("Dismiss")}
			</button>
		`).click(() => edit_button.toggle_edit_mode());
		dismiss_button.hide();

		edit_box.set_value(pg.content);

		edit_box.on_submit = (value) => {
			content_wrapper.empty();
			content_wrapper.append(value);
			edit_button.prop("disabled", true);
			edit_box.quill.enable(false);

			pg.content = value;
			this.update_comment(pg.name, value)
				.then(edit_button.toggle_edit_mode)
				.finally(() => {
					edit_button.prop("disabled", false);
					edit_box.quill.enable(true);
				});
		};

		content_wrapper.after(edit_wrapper);

		let edit_button = $();
		let current_user = jingrow.session.user;
		if (["Administrator", pg.owner].includes(current_user)) {
			edit_button = $(`<button class="btn btn-link action-btn">${__("Edit")}</a>`).click(
				() => {
					edit_button.edit_mode ? edit_box.submit() : edit_button.toggle_edit_mode();
				}
			);
		}

		edit_button.toggle_edit_mode = () => {
			edit_button.edit_mode = !edit_button.edit_mode;
			edit_button.text(edit_button.edit_mode ? __("Save") : __("Edit"));
			more_actions_wrapper.toggle(!edit_button.edit_mode);
			dismiss_button.toggle(edit_button.edit_mode);
			edit_wrapper.toggle(edit_button.edit_mode);
			content_wrapper.toggle(!edit_button.edit_mode);
		};
		let actions_wrapper = comment_wrapper.find(".custom-actions");
		actions_wrapper.append(edit_button);
		actions_wrapper.append(dismiss_button);
	}

	make_editable(container) {
		return jingrow.ui.form.make_control({
			parent: container,
			df: {
				fieldtype: "Comment",
				fieldname: "comment",
				label: "Comment",
			},
			enable_mentions: true,
			render_input: true,
			only_input: true,
			no_wrapper: true,
		});
	}

	update_comment(name, content) {
		return jingrow
			.xcall("jingrow.desk.form.utils.update_comment", { name, content })
			.then(() => {
				jingrow.utils.play_sound("click");
			});
	}

	get_last_email(from_recipient) {
		/**
		 * Return the latest email communication.
		 *
		 * @param {boolean} from_recipient If true, only considers emails where current form's recipient is the sender.
		 * @returns {object|null} The latest email communication, or null if no communication is found.
		 */

		const communications = this.frm.get_pageinfo().communications || [];
		const recipient = this.get_recipient();

		const filtered_records = communications
			.filter(
				(record) =>
					record.communication_type === "Communication" &&
					record.communication_medium === "Email" &&
					(!from_recipient || record.sender === recipient)
			)
			.sort((a, b) => b.creation - a.creation);

		return filtered_records[0] || null;
	}

	delete_comment(comment_name) {
		jingrow.confirm(__("Delete comment?"), () => {
			return jingrow
				.xcall("jingrow.client.delete", {
					pagetype: "Comment",
					name: comment_name,
				})
				.then(() => {
					jingrow.utils.play_sound("delete");
				});
		});
	}

	copy_link(ev) {
		let pg_link = jingrow.urllib.get_full_url(
			jingrow.utils.get_form_link(this.frm.pagetype, this.frm.pagename)
		);
		let element_id = $(ev.currentTarget).closest(".timeline-content").attr("id");
		jingrow.utils.copy_to_clipboard(`${pg_link}#${element_id}`);
	}
}

export default FormTimeline;
