import KanbanSettings from "./kanban_settings";

jingrow.provide("jingrow.views");

jingrow.views.KanbanView = class KanbanView extends jingrow.views.ListView {
	static no_sidebar = true;

	static load_last_view() {
		const route = jingrow.get_route();
		if (route.length === 3) {
			const pagetype = route[1];
			const user_settings = jingrow.get_user_settings(pagetype)["Kanban"] || {};
			if (!user_settings.last_kanban_board) {
				return new jingrow.views.KanbanView({ pagetype: pagetype });
			}

			route.push(user_settings.last_kanban_board);
			jingrow.set_route(route);
			return true;
		}
		return false;
	}

	get view_name() {
		return "Kanban";
	}

	show() {
		jingrow.views.KanbanView.get_kanbans(this.pagetype).then((kanbans) => {
			if (!kanbans.length) {
				return jingrow.views.KanbanView.show_kanban_dialog(this.pagetype, true);
			} else if (kanbans.length && jingrow.get_route().length !== 4) {
				return jingrow.views.KanbanView.show_kanban_dialog(this.pagetype, true);
			} else {
				this.kanbans = kanbans;

				return jingrow.run_serially([
					() => this.show_skeleton(),
					() => this.fetch_meta(),
					() => this.hide_skeleton(),
					() => this.check_permissions(),
					() => this.init(),
					() => this.before_refresh(),
					() => this.refresh(),
				]);
			}
		});
	}

	init() {
		return super.init().then(() => {
			let menu_length = this.page.menu.find(".dropdown-item").length;
			if (menu_length === 1) {
				// Only 'Refresh' (hidden) is present (always), dropdown is visibly empty
				this.page.hide_menu();
			}
		});
	}

	setup_defaults() {
		return super.setup_defaults().then(() => {
			let get_board_name = () => {
				return this.kanbans.length && this.kanbans[0].name;
			};

			this.board_name = jingrow.get_route()[3] || get_board_name() || null;
			this.page_title = __(this.board_name);
			this.card_meta = this.get_card_meta();
			this.page_length = 0;

			return jingrow.run_serially([
				() => this.set_board_perms_and_push_menu_items(),
				() => this.get_board(),
			]);
		});
	}

	set_board_perms_and_push_menu_items() {
		// needs server-side call as client-side document instance is absent before kanban render
		return jingrow.call({
			method: "jingrow.client.get_pg_permissions",
			args: {
				pagetype: "Kanban Board",
				pagename: this.board_name,
			},
			callback: (result) => {
				this.board_perms = result.message.permissions || {};
				this.push_menu_items();
			},
		});
	}

	push_menu_items() {
		if (this.board_perms.write) {
			this.menu_items.push({
				label: __("Save filters"),
				action: () => {
					this.save_kanban_board_filters();
				},
			});
		}

		if (this.board_perms.delete) {
			this.menu_items.push({
				label: __("Delete Kanban Board"),
				action: () => {
					jingrow.confirm(__("Are you sure you want to proceed?"), () => {
						jingrow.db.delete_pg("Kanban Board", this.board_name).then(() => {
							jingrow.show_alert(`Kanban Board ${this.board_name} deleted.`);
							jingrow.set_route("List", this.pagetype, "List");
						});
					});
				},
			});
		}
	}

	setup_paging_area() {
		// pass
	}

	toggle_result_area() {
		this.$result.toggle(this.data.length > 0);
	}

	get_board() {
		return jingrow.db.get_pg("Kanban Board", this.board_name).then((board) => {
			this.board = board;
			this.board.filters_array = JSON.parse(this.board.filters || "[]");
			this.board.fields = JSON.parse(this.board.fields || "[]");
			this.filters = this.board.filters_array;
		});
	}

	setup_page() {
		this.hide_page_form = true;
		this.hide_card_layout = true;
		this.hide_sort_selector = true;
		super.setup_page();
	}

	setup_view() {
		if (this.board.columns.filter((col) => col.status !== "Archived").length > 5) {
			this.page.container.addClass("full-width");
		}
		this.setup_realtime_updates();
		this.setup_like();
	}

	set_fields() {
		super.set_fields();
		this._add_field(this.card_meta.title_field);
	}

	before_render() {
		jingrow.model.user_settings.save(this.pagetype, "last_view", this.view_name);
		this.save_view_user_settings({
			last_kanban_board: this.board_name,
		});
	}

	render_list() {}

	on_filter_change() {
		if (!this.board_perms.write) return; // avoid misleading ux

		if (JSON.stringify(this.board.filters_array) !== JSON.stringify(this.filter_area.get())) {
			this.page.set_indicator(__("Not Saved"), "orange");
		} else {
			this.page.clear_indicator();
		}
	}

	save_kanban_board_filters() {
		const filters = this.filter_area.get();

		jingrow.db.set_value("Kanban Board", this.board_name, "filters", filters).then((r) => {
			if (r.exc) {
				jingrow.show_alert({
					indicator: "red",
					message: __("There was an error saving filters"),
				});
				return;
			}
			jingrow.show_alert({
				indicator: "green",
				message: __("Filters saved"),
			});

			this.board.filters_array = filters;
			this.on_filter_change();
		});
	}

	get_fields() {
		this.fields.push([this.board.field_name, this.board.reference_pagetype]);
		return super.get_fields();
	}

	render() {
		const board_name = this.board_name;
		if (!this.kanban) {
			this.kanban = new jingrow.views.KanbanBoard({
				pagetype: this.pagetype,
				board: this.board,
				board_name: board_name,
				cards: this.data,
				card_meta: this.card_meta,
				wrapper: this.$result,
				cur_list: this,
				user_settings: this.view_user_settings,
			});
		} else if (board_name === this.kanban.board_name) {
			this.kanban.update(this.data);
		}
	}

	get_card_meta() {
		var meta = jingrow.get_meta(this.pagetype);
		// preserve route options erased by new pg
		let route_options = { ...jingrow.route_options };
		var pg = jingrow.model.get_new_pg(this.pagetype);
		jingrow.route_options = route_options;
		var title_field = null;
		var quick_entry = false;

		if (this.meta.title_field) {
			title_field = jingrow.meta.get_field(this.pagetype, this.meta.title_field);
		}

		this.meta.fields.forEach((df) => {
			const is_valid_field =
				["Data", "Text", "Small Text", "Text Editor"].includes(df.fieldtype) && !df.hidden;

			if (is_valid_field && !title_field) {
				// can be mapped to textarea
				title_field = df;
			}
		});

		// quick entry
		var mandatory = meta.fields.filter((df) => df.reqd && !pg[df.fieldname]);

		if (
			mandatory.some((df) => jingrow.model.table_fields.includes(df.fieldtype)) ||
			mandatory.length > 1
		) {
			quick_entry = true;
		}

		if (!title_field) {
			title_field = jingrow.meta.get_field(this.pagetype, "name");
		}

		return {
			quick_entry: quick_entry,
			title_field: title_field,
		};
	}

	get_view_settings() {
		return {
			label: __("Kanban Settings", null, "Button in kanban view menu"),
			action: () => this.show_kanban_settings(),
			standard: true,
		};
	}

	show_kanban_settings() {
		jingrow.model.with_pagetype(this.pagetype, () => {
			new KanbanSettings({
				kanbanview: this,
				pagetype: this.pagetype,
				settings: this.board,
				meta: jingrow.get_meta(this.pagetype),
			});
		});
	}

	get required_libs() {
		return "kanban_board.bundle.js";
	}
};

jingrow.views.KanbanView.get_kanbans = function (pagetype) {
	let kanbans = [];

	return get_kanban_boards().then((kanban_boards) => {
		if (kanban_boards) {
			kanban_boards.forEach((board) => {
				let route = `/app/${jingrow.router.slug(board.reference_pagetype)}/view/kanban/${
					board.name
				}`;
				kanbans.push({ name: board.name, route: route });
			});
		}

		return kanbans;
	});

	function get_kanban_boards() {
		return jingrow
			.call("jingrow.desk.pagetype.kanban_board.kanban_board.get_kanban_boards", { pagetype })
			.then((r) => r.message);
	}
};

jingrow.views.KanbanView.show_kanban_dialog = function (pagetype) {
	let dialog = new_kanban_dialog();
	dialog.show();

	function make_kanban_board(board_name, field_name, project) {
		return jingrow.call({
			method: "jingrow.desk.pagetype.kanban_board.kanban_board.quick_kanban_board",
			args: {
				pagetype,
				board_name,
				field_name,
				project,
			},
			callback: function (r) {
				var kb = r.message;
				if (kb.filters) {
					jingrow.provide("jingrow.kanban_filters");
					jingrow.kanban_filters[kb.kanban_board_name] = kb.filters;
				}
				jingrow.set_route("List", pagetype, "Kanban", kb.kanban_board_name);
			},
		});
	}

	function new_kanban_dialog() {
		/* Kanban dialog can show either "Save" or "Customize Form" option depending if any Select fields exist in the PageType for Kanban creation
		 */

		const select_fields = jingrow.get_meta(pagetype).fields.filter((df) => {
			return df.fieldtype === "Select" && df.fieldname !== "kanban_column";
		});
		const dialog_fields = get_fields_for_dialog(select_fields);
		const to_save = select_fields.length > 0;
		const primary_action_label = to_save ? __("Save") : __("Customize Form");
		const dialog_title = to_save ? __("New Kanban Board") : __("No Select Field Found");

		let primary_action = () => {
			if (to_save) {
				const values = dialog.get_values();
				make_kanban_board(values.board_name, values.field_name, values.project).then(
					() => dialog.hide(),
					(err) => jingrow.msgprint(err)
				);
			} else {
				jingrow.set_route("Form", "Customize Form", { pg_type: pagetype });
			}
		};

		return new jingrow.ui.Dialog({
			title: dialog_title,
			fields: dialog_fields,
			primary_action_label,
			primary_action,
		});
	}

	function get_fields_for_dialog(select_fields) {
		if (!select_fields.length) {
			return [
				{
					fieldtype: "HTML",
					options: `
					<div>
						<p class="text-medium">
						${__(
							'No fields found that can be used as a Kanban Column. Use the Customize Form to add a Custom Field of type "Select".'
						)}
						</p>
					</div>
				`,
				},
			];
		}

		let fields = [
			{
				fieldtype: "Data",
				fieldname: "board_name",
				label: __("Kanban Board Name"),
				reqd: 1,
				description: ["Note", "ToDo"].includes(pagetype)
					? __("This Kanban Board will be private")
					: "",
			},
			{
				fieldtype: "Select",
				fieldname: "field_name",
				label: __("Columns based on"),
				options: select_fields.map((df) => ({ label: df.label, value: df.fieldname })),
				default: select_fields[0],
				reqd: 1,
			},
		];

		if (pagetype === "Task") {
			fields.push({
				fieldtype: "Link",
				fieldname: "project",
				label: __("Project"),
				options: "Project",
			});
		}

		return fields;
	}
};
