# Copyright (c) 2015, JINGROW
# License: MIT. See LICENSE

import json

import jingrow
from jingrow import _
from jingrow.model.page import Page


class KanbanBoard(Page):
	# begin: auto-generated types
	# This code is auto-generated. Do not modify anything in this block.

	from typing import TYPE_CHECKING

	if TYPE_CHECKING:
		from jingrow.desk.pagetype.kanban_board_column.kanban_board_column import KanbanBoardColumn
		from jingrow.types import DF

		columns: DF.Table[KanbanBoardColumn]
		field_name: DF.Literal[None]
		fields: DF.Code | None
		filters: DF.Code | None
		kanban_board_name: DF.Data
		private: DF.Check
		reference_pagetype: DF.Link
		show_labels: DF.Check

	# end: auto-generated types
	def validate(self):
		self.validate_column_name()

	def on_change(self):
		jingrow.clear_cache(pagetype=self.reference_pagetype)
		jingrow.cache.delete_keys("_user_settings")

	def before_insert(self):
		for column in self.columns:
			column.order = get_order_for_column(self, column.column_name)

	def validate_column_name(self):
		for column in self.columns:
			if not column.column_name:
				jingrow.msgprint(_("Column Name cannot be empty"), raise_exception=True)


def get_permission_query_conditions(user):
	if not user:
		user = jingrow.session.user

	if user == "Administrator":
		return ""

	return f"""(`tabKanban Board`.private=0 or `tabKanban Board`.owner={jingrow.db.escape(user)})"""


def has_permission(pg, ptype, user):
	if pg.private == 0 or user == "Administrator":
		return True

	if user == pg.owner:
		return True

	return False


@jingrow.whitelist()
def get_kanban_boards(pagetype):
	"""Get Kanban Boards for pagetype to show in List View"""
	return jingrow.get_list(
		"Kanban Board",
		fields=["name", "filters", "reference_pagetype", "private"],
		filters={"reference_pagetype": pagetype},
	)


@jingrow.whitelist()
def add_column(board_name, column_title):
	"""Adds new column to Kanban Board"""
	pg = jingrow.get_pg("Kanban Board", board_name)
	for col in pg.columns:
		if column_title == col.column_name:
			jingrow.throw(_("Column <b>{0}</b> already exist.").format(column_title))

	pg.append("columns", dict(column_name=column_title))
	pg.save()
	return pg.columns


@jingrow.whitelist()
def archive_restore_column(board_name, column_title, status):
	"""Set column's status to status"""
	pg = jingrow.get_pg("Kanban Board", board_name)
	for col in pg.columns:
		if column_title == col.column_name:
			col.status = status

	pg.save()
	return pg.columns


@jingrow.whitelist()
def update_order(board_name, order):
	"""Save the order of cards in columns"""
	board = jingrow.get_pg("Kanban Board", board_name)
	pagetype = board.reference_pagetype
	updated_cards = []

	if not jingrow.has_permission(pagetype, "write"):
		# Return board data from db
		return board, updated_cards

	fieldname = board.field_name
	order_dict = json.loads(order)

	for col_name, cards in order_dict.items():
		for card in cards:
			column = jingrow.get_value(pagetype, {"name": card}, fieldname)
			if column != col_name:
				jingrow.set_value(pagetype, card, fieldname, col_name)
				updated_cards.append(dict(name=card, column=col_name))

		for column in board.columns:
			if column.column_name == col_name:
				column.order = json.dumps(cards)

	return board.save(ignore_permissions=True), updated_cards


@jingrow.whitelist()
def update_order_for_single_card(board_name, pagename, from_colname, to_colname, old_index, new_index):
	"""Save the order of cards in columns"""
	board = jingrow.get_pg("Kanban Board", board_name)
	pagetype = board.reference_pagetype

	jingrow.has_permission(pagetype, "write", throw=True)

	fieldname = board.field_name
	old_index = jingrow.parse_json(old_index)
	new_index = jingrow.parse_json(new_index)

	# save current order and index of columns to be updated
	from_col_order, from_col_idx = get_kanban_column_order_and_index(board, from_colname)
	to_col_order, to_col_idx = get_kanban_column_order_and_index(board, to_colname)

	if from_colname == to_colname:
		from_col_order = to_col_order

	if from_col_order:
		to_col_order.insert(new_index, from_col_order.pop(old_index))

	# save updated order
	board.columns[from_col_idx].order = jingrow.as_json(from_col_order)
	board.columns[to_col_idx].order = jingrow.as_json(to_col_order)
	board.save(ignore_permissions=True)

	# update changed value in pg
	jingrow.set_value(pagetype, pagename, fieldname, to_colname)

	return board


def get_kanban_column_order_and_index(board, colname):
	for i, col in enumerate(board.columns):
		if col.column_name == colname:
			col_order = jingrow.parse_json(col.order)
			col_idx = i

	return col_order, col_idx


@jingrow.whitelist()
def add_card(board_name, pagename, colname):
	board = jingrow.get_pg("Kanban Board", board_name)

	jingrow.has_permission(board.reference_pagetype, "write", throw=True)

	col_order, col_idx = get_kanban_column_order_and_index(board, colname)
	col_order.insert(0, pagename)

	board.columns[col_idx].order = jingrow.as_json(col_order)

	return board.save(ignore_permissions=True)


@jingrow.whitelist()
def quick_kanban_board(pagetype, board_name, field_name, project=None):
	"""Create new KanbanBoard quickly with default options"""

	pg = jingrow.new_pg("Kanban Board")
	meta = jingrow.get_meta(pagetype)

	pg.kanban_board_name = board_name
	pg.reference_pagetype = pagetype
	pg.field_name = field_name

	if project:
		pg.filters = f'[["Task","project","=","{project}"]]'

	options = ""
	for field in meta.fields:
		if field.fieldname == field_name:
			options = field.options

	columns = []
	if options:
		columns = options.split("\n")

	for column in columns:
		if not column:
			continue
		pg.append("columns", dict(column_name=column))

	if pagetype in ["Note", "ToDo"]:
		pg.private = 1

	pg.save()
	return pg


def get_order_for_column(board, colname):
	filters = [[board.reference_pagetype, board.field_name, "=", colname]]
	if board.filters:
		filters.append(jingrow.parse_json(board.filters)[0])

	return jingrow.as_json(jingrow.get_list(board.reference_pagetype, filters=filters, pluck="name"))


@jingrow.whitelist()
def update_column_order(board_name, order):
	"""Set the order of columns in Kanban Board"""
	board = jingrow.get_pg("Kanban Board", board_name)
	order = json.loads(order)
	old_columns = board.columns
	new_columns = []

	for col in order:
		for column in list(old_columns):
			if col == column.column_name:
				new_columns.append(column)
				old_columns.remove(column)

	new_columns.extend(old_columns)

	board.columns = []
	for col in new_columns:
		board.append(
			"columns",
			dict(
				column_name=col.column_name,
				status=col.status,
				order=col.order,
				indicator=col.indicator,
			),
		)

	board.save()
	return board


@jingrow.whitelist()
def set_indicator(board_name, column_name, indicator):
	"""Set the indicator color of column"""
	board = jingrow.get_pg("Kanban Board", board_name)

	for column in board.columns:
		if column.column_name == column_name:
			column.indicator = indicator

	board.save()
	return board


@jingrow.whitelist()
def save_settings(board_name: str, settings: str) -> Page:
	settings = json.loads(settings)
	pg = jingrow.get_pg("Kanban Board", board_name)

	fields = settings["fields"]
	if not isinstance(fields, str):
		fields = json.dumps(fields)

	pg.fields = fields
	pg.show_labels = settings["show_labels"]
	pg.save()

	resp = pg.as_dict()
	resp["fields"] = jingrow.parse_json(resp["fields"])

	return resp
