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

import json

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


class InvalidAppOrder(jingrow.ValidationError):
	pass


class InstalledApplications(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.core.pagetype.installed_application.installed_application import InstalledApplication
		from jingrow.types import DF

		installed_applications: DF.Table[InstalledApplication]

	# end: auto-generated types
	def update_versions(self):
		self.delete_key("installed_applications")
		for app in jingrow.utils.get_installed_apps_info():
			self.append(
				"installed_applications",
				{
					"app_name": app.get("app_name"),
					"app_version": app.get("version") or "UNVERSIONED",
					"git_branch": app.get("branch") or "UNVERSIONED",
				},
			)
		self.save()


@jingrow.whitelist()
def update_installed_apps_order(new_order: list[str] | str):
	"""Change the ordering of `installed_apps` global

	This list is used to resolve hooks and by default it's order of installation on site.

	Sometimes it might not be the ordering you want, so thie function is provided to override it.
	"""
	jingrow.only_for("System Manager")

	if isinstance(new_order, str):
		new_order = json.loads(new_order)

	jingrow.local.request_cache and jingrow.local.request_cache.clear()
	existing_order = jingrow.get_installed_apps(_ensure_on_bench=True)

	if set(existing_order) != set(new_order) or not isinstance(new_order, list):
		jingrow.throw(
			_("You are only allowed to update order, do not remove or add apps."), exc=InvalidAppOrder
		)

	# Ensure jingrow is always first regardless of user's preference.
	if "jingrow" in new_order:
		new_order.remove("jingrow")
	new_order.insert(0, "jingrow")

	jingrow.db.set_global("installed_apps", json.dumps(new_order))

	_create_version_log_for_change(existing_order, new_order)


def _create_version_log_for_change(old, new):
	version = jingrow.new_pg("Version")
	version.ref_pagetype = "DefaultValue"
	version.pagename = "installed_apps"
	version.data = jingrow.as_json({"changed": [["current", json.dumps(old), json.dumps(new)]]})
	version.flags.ignore_links = True  # This is a fake pagetype
	version.flags.ignore_permissions = True
	version.insert()


@jingrow.whitelist()
def get_installed_app_order() -> list[str]:
	jingrow.only_for("System Manager")

	return jingrow.get_installed_apps(_ensure_on_bench=True)
