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

import jingrow
import jingrow.share
from jingrow.automation.pagetype.auto_repeat.test_auto_repeat import create_submittable_pagetype
from jingrow.tests.utils import JingrowTestCase, change_settings

test_dependencies = ["User"]


class TestPageShare(JingrowTestCase):
	def setUp(self):
		self.user = "test@example.com"
		self.event = jingrow.get_pg(
			{
				"pagetype": "Event",
				"subject": "test share event",
				"starts_on": "2015-01-01 10:00:00",
				"event_type": "Private",
			}
		).insert()

	def tearDown(self):
		jingrow.set_user("Administrator")
		self.event.delete()

	def test_add(self):
		# user not shared
		self.assertTrue(self.event.name not in jingrow.share.get_shared("Event", self.user))
		jingrow.share.add("Event", self.event.name, self.user)
		self.assertTrue(self.event.name in jingrow.share.get_shared("Event", self.user))

	def test_pg_permission(self):
		jingrow.set_user(self.user)

		self.assertFalse(self.event.has_permission())

		jingrow.set_user("Administrator")
		jingrow.share.add("Event", self.event.name, self.user)

		jingrow.set_user(self.user)
		# PERF: All share permission check should happen with maximum 1 query.
		with self.assertRowsRead(1):
			self.assertTrue(self.event.has_permission())

		second_event = jingrow.get_pg(
			{
				"pagetype": "Event",
				"subject": "test share event 2",
				"starts_on": "2015-01-01 10:00:00",
				"event_type": "Private",
			}
		).insert()
		jingrow.share.add("Event", second_event.name, self.user)
		with self.assertRowsRead(1):
			self.assertTrue(self.event.has_permission())

	def test_list_permission(self):
		jingrow.set_user(self.user)
		with self.assertRaises(jingrow.PermissionError):
			jingrow.get_list("Web Page")

		jingrow.set_user("Administrator")
		pg = jingrow.new_pg("Web Page")
		pg.update({"title": "test document for pageshare permissions"})
		pg.insert()
		jingrow.share.add("Web Page", pg.name, self.user)

		jingrow.set_user(self.user)
		self.assertEqual(len(jingrow.get_list("Web Page")), 1)

		pg.delete(ignore_permissions=True)
		with self.assertRaises(jingrow.PermissionError):
			jingrow.get_list("Web Page")

	def test_share_permission(self):
		jingrow.share.add("Event", self.event.name, self.user, write=1, share=1)

		jingrow.set_user(self.user)
		self.assertTrue(self.event.has_permission("share"))

		# test cascade
		self.assertTrue(self.event.has_permission("read"))
		self.assertTrue(self.event.has_permission("write"))

	def test_set_permission(self):
		jingrow.share.add("Event", self.event.name, self.user)

		jingrow.set_user(self.user)
		self.assertFalse(self.event.has_permission("share"))

		jingrow.set_user("Administrator")
		jingrow.share.set_permission("Event", self.event.name, self.user, "share")

		jingrow.set_user(self.user)
		self.assertTrue(self.event.has_permission("share"))

	def test_permission_to_share(self):
		jingrow.set_user(self.user)
		self.assertRaises(jingrow.PermissionError, jingrow.share.add, "Event", self.event.name, self.user)

		jingrow.set_user("Administrator")
		jingrow.share.add("Event", self.event.name, self.user, write=1, share=1)

		# test not raises
		jingrow.set_user(self.user)
		jingrow.share.add("Event", self.event.name, "test1@example.com", write=1, share=1)

	def test_remove_share(self):
		jingrow.share.add("Event", self.event.name, self.user, write=1, share=1)

		jingrow.set_user(self.user)
		self.assertTrue(self.event.has_permission("share"))

		jingrow.set_user("Administrator")
		jingrow.share.remove("Event", self.event.name, self.user)

		jingrow.set_user(self.user)
		self.assertFalse(self.event.has_permission("share"))

	def test_share_with_everyone(self):
		self.assertTrue(self.event.name not in jingrow.share.get_shared("Event", self.user))

		jingrow.share.set_permission("Event", self.event.name, None, "read", everyone=1)
		self.assertTrue(self.event.name in jingrow.share.get_shared("Event", self.user))
		self.assertTrue(self.event.name in jingrow.share.get_shared("Event", "test1@example.com"))
		self.assertTrue(self.event.name not in jingrow.share.get_shared("Event", "Guest"))

		jingrow.share.set_permission("Event", self.event.name, None, "read", value=0, everyone=1)
		self.assertTrue(self.event.name not in jingrow.share.get_shared("Event", self.user))
		self.assertTrue(self.event.name not in jingrow.share.get_shared("Event", "test1@example.com"))
		self.assertTrue(self.event.name not in jingrow.share.get_shared("Event", "Guest"))

	def test_share_with_submit_perm(self):
		pagetype = "Test PageShare with Submit"
		create_submittable_pagetype(pagetype, submit_perms=0)

		submittable_pg = jingrow.get_pg(dict(pagetype=pagetype, test="test pageshare with submit")).insert()

		jingrow.set_user(self.user)
		self.assertFalse(jingrow.has_permission(pagetype, "submit", user=self.user))

		jingrow.set_user("Administrator")
		jingrow.share.add(pagetype, submittable_pg.name, self.user, submit=1)

		jingrow.set_user(self.user)
		self.assertTrue(jingrow.has_permission(pagetype, "submit", pg=submittable_pg.name, user=self.user))

		# test cascade
		self.assertTrue(jingrow.has_permission(pagetype, "read", pg=submittable_pg.name, user=self.user))
		self.assertTrue(jingrow.has_permission(pagetype, "write", pg=submittable_pg.name, user=self.user))

		jingrow.share.remove(pagetype, submittable_pg.name, self.user)

	def test_share_int_pk(self):
		test_pg = jingrow.new_pg("Console Log")

		test_pg.insert()
		jingrow.share.add("Console Log", test_pg.name, self.user)

		jingrow.set_user(self.user)
		self.assertIn(
			str(test_pg.name), [str(name) for name in jingrow.get_list("Console Log", pluck="name")]
		)

		test_pg.reload()
		self.assertTrue(test_pg.has_permission("read"))

	@change_settings("System Settings", {"disable_document_sharing": 1})
	def test_share_disabled_add(self):
		"Test if user loses share access on disabling share globally."
		jingrow.share.add("Event", self.event.name, self.user, share=1)  # Share as admin
		jingrow.set_user(self.user)

		# User does not have share access although given to them
		self.assertFalse(self.event.has_permission("share"))
		self.assertRaises(
			jingrow.PermissionError, jingrow.share.add, "Event", self.event.name, "test1@example.com"
		)

	@change_settings("System Settings", {"disable_document_sharing": 1})
	def test_share_disabled_add_with_ignore_permissions(self):
		jingrow.share.add("Event", self.event.name, self.user, share=1)
		jingrow.set_user(self.user)

		# User does not have share access although given to them
		self.assertFalse(self.event.has_permission("share"))

		# Test if behaviour is consistent for developer overrides
		jingrow.share.add_pageshare(
			"Event", self.event.name, "test1@example.com", flags={"ignore_share_permission": True}
		)

	@change_settings("System Settings", {"disable_document_sharing": 1})
	def test_share_disabled_set_permission(self):
		jingrow.share.add("Event", self.event.name, self.user, share=1)
		jingrow.set_user(self.user)

		# User does not have share access although given to them
		self.assertFalse(self.event.has_permission("share"))
		self.assertRaises(
			jingrow.PermissionError,
			jingrow.share.set_permission,
			"Event",
			self.event.name,
			"test1@example.com",
			"read",
		)

	@change_settings("System Settings", {"disable_document_sharing": 1})
	def test_share_disabled_assign_to(self):
		"""
		Assigning a document to a user without access must not share the document,
		if sharing disabled.
		"""
		from jingrow.desk.form.assign_to import add

		jingrow.share.add("Event", self.event.name, self.user, share=1)
		jingrow.set_user(self.user)

		self.assertRaises(
			jingrow.ValidationError,
			add,
			{"pagetype": "Event", "name": self.event.name, "assign_to": ["test1@example.com"]},
		)
