import json
import os
import time

import frappe
import requests
import urllib3

# Suppress SSL warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

SERVERS_FILE = "/home/frappe/frappe-bench/apps/admin_panel/templates/servers.json"
CERTS_DIR = "/home/frappe/frappe-bench/apps/admin_panel/certs"
CLIENT_CERT = os.path.join(CERTS_DIR, "client.crt")
CLIENT_KEY = os.path.join(CERTS_DIR, "client.key")

DEFAULT_VOLUMES = [
	{"name": "mysql", "source_path": "/var/lib/mysql", "device_name": "mysql"},
	{"name": "frontend", "source_path": "/home/frappe/frappe-bench/sites/frontend", "device_name": "frontend"},
]


def _check_admin_permission():
	"""Check if user has admin permission."""
	if frappe.session.user == "Guest":
		frappe.throw("Please login to access this feature", frappe.AuthenticationError)
	if frappe.session.user == "Administrator":
		return
	roles = frappe.get_roles()
	if "System Manager" not in roles and "Administrator" not in roles:
		frappe.throw("You need System Manager or Administrator role", frappe.PermissionError)


def _load_servers():
	"""Load servers config from JSON file."""
	if os.path.exists(SERVERS_FILE):
		with open(SERVERS_FILE, "r") as f:
			return json.load(f)
	return {}


def _get_server_config(server_name):
	"""Get server URL and client certificate paths."""
	servers = _load_servers()
	server = servers.get(server_name, {})
	url = server.get("url", "")

	return {
		"url": url,
		"cert": CLIENT_CERT if os.path.exists(CLIENT_CERT) else None,
		"key": CLIENT_KEY if os.path.exists(CLIENT_KEY) else None,
	}


def _incus_api(server_name, method, path, data=None, timeout=30):
	"""Make REST API request to a specific Incus server."""
	config = _get_server_config(server_name)

	if not config["url"]:
		raise Exception(f"Server '{server_name}' URL not found")

	if not config["cert"] or not config["key"]:
		raise Exception("Panel certificate not configured. Please generate a certificate in Servers tab.")

	url = f"{config['url']}{path}"

	try:
		r = requests.request(
			method,
			url,
			headers={"Content-Type": "application/json"},
			cert=(config["cert"], config["key"]),
			verify=False,
			json=data,
			timeout=timeout,
		)
		r.raise_for_status()
		return r.json()
	except requests.exceptions.ConnectionError:
		raise Exception(f"Cannot connect to server '{server_name}' at {config['url']}")
	except requests.exceptions.Timeout:
		raise Exception(f"Connection to '{server_name}' timed out")
	except requests.exceptions.HTTPError as e:
		raise Exception(f"Server '{server_name}' error: {e.response.status_code}")


def _wait_for_operation(server_name, operation_url, timeout=60):
	"""Wait for an Incus async operation to complete."""
	if not operation_url:
		return
	wait_path = f"{operation_url}/wait"
	try:
		result = _incus_api(server_name, "GET", f"{wait_path}?timeout={timeout}")
		return result
	except Exception:
		return None


def _extract_ip(state_data):
	"""Extract IPv4 address from Incus state network data."""
	network = state_data.get("metadata", {}).get("network", {})
	for iface_name, iface in network.items():
		if iface_name == "lo":
			continue
		for addr in iface.get("addresses", []):
			if addr.get("family") == "inet" and addr.get("scope") == "global":
				return addr.get("address", "")
	return ""


def _get_cloud_containers():
	"""Get data from Cloud Container doctype if available."""
	try:
		containers = frappe.get_all(
			"Cloud Container",
			fields=["name", "container_name", "image", "owner", "ip_address", "status"],
		)
		return {c.get("container_name", c.get("name")): c for c in containers}
	except Exception:
		return {}


@frappe.whitelist()
def get_images(target_server=None):
	"""Get available images from a specific Incus server."""
	_check_admin_permission()

	if not target_server:
		return {"error": "Server name is required"}

	try:
		resp = _incus_api(target_server, "GET", "/1.0/images?recursion=1")
	except Exception as e:
		return {"error": str(e)}

	images = []
	for img in resp.get("metadata", []):
		aliases = img.get("aliases", [])
		props = img.get("properties", {})
		fingerprint = img.get("fingerprint", "")

		alias = aliases[0]["name"] if aliases else ""
		description = props.get("description", "") or alias or fingerprint[:12]

		images.append({
			"alias": alias,
			"description": description,
			"os": props.get("os", ""),
			"architecture": img.get("architecture", ""),
			"size": img.get("size", 0),
			"fingerprint": fingerprint,
			"created_at": img.get("created_at", ""),
		})

	return images


@frappe.whitelist()
def get_all_containers(target_server=None):
	"""Get list of all containers from a specific Incus server."""
	_check_admin_permission()

	if not target_server:
		return {"error": "Server name is required"}

	try:
		resp = _incus_api(target_server, "GET", "/1.0/instances?recursion=1")
	except Exception as e:
		return {"error": str(e)}

	cloud_data = _get_cloud_containers()

	containers = []
	for inst in resp.get("metadata", []):
		name = inst.get("name", "")
		status = inst.get("status", "Unknown")
		config = inst.get("config", {})
		created_at = inst.get("created_at", "")
		architecture = inst.get("architecture", "")
		container_type = inst.get("type", "container")

		# Get IP from state if running
		ip_address = ""
		state = inst.get("state", {})
		if state and status == "Running":
			network = state.get("network", {})
			for iface_name, iface in network.items():
				if iface_name == "lo":
					continue
				for addr in iface.get("addresses", []):
					if addr.get("family") == "inet" and addr.get("scope") == "global":
						ip_address = addr.get("address", "")
						break
				if ip_address:
					break

		image = config.get("image.description", config.get("image.os", ""))
		cloud = cloud_data.get(name, {})

		containers.append({
			"name": name,
			"container_name": name,
			"status": status,
			"ip_address": ip_address or cloud.get("ip_address", ""),
			"image": image or cloud.get("image", ""),
			"owner": cloud.get("owner", ""),
			"created": created_at[:10] if created_at else "",
			"architecture": architecture,
			"type": container_type,
			"server": target_server,
		})

	return containers


@frappe.whitelist()
def get_container_detail(container_name, target_server=None):
	"""Get detailed container info including resource usage."""
	_check_admin_permission()

	if not target_server:
		return {"error": "Server name is required"}

	try:
		detail = _incus_api(target_server, "GET", f"/1.0/instances/{container_name}")
	except Exception as e:
		return {"error": str(e), "name": container_name, "status": "Error"}

	meta = detail.get("metadata", {})
	config = meta.get("config", {})
	status = meta.get("status", "Unknown")
	created_at = meta.get("created_at", "")

	result = {
		"name": container_name,
		"container_name": container_name,
		"status": status,
		"ip_address": "",
		"image": config.get("image.description", config.get("image.os", "")),
		"owner": "",
		"created": created_at[:10] if created_at else "",
		"architecture": meta.get("architecture", ""),
		"type": meta.get("type", "container"),
		"profiles": meta.get("profiles", []),
		"cpu_usage": 0,
		"ram_usage": 0,
		"disk_usage": 0,
		"memory_usage_bytes": 0,
		"memory_total_bytes": 0,
		"disk_usage_bytes": 0,
		"disk_total_bytes": 0,
		"network_rx": 0,
		"network_tx": 0,
		"connections": 0,
		"uptime": "-",
		"server": target_server,
	}

	# Enrich with Cloud Container data
	cloud_data = _get_cloud_containers()
	cloud = cloud_data.get(container_name, {})
	if cloud:
		result["owner"] = cloud.get("owner", "")
		if not result["image"]:
			result["image"] = cloud.get("image", "")

	# Get state if running
	if status == "Running":
		try:
			state = _incus_api(target_server, "GET", f"/1.0/instances/{container_name}/state")
			state_meta = state.get("metadata", {})

			result["ip_address"] = _extract_ip(state)
			if not result["ip_address"] and cloud:
				result["ip_address"] = cloud.get("ip_address", "")

			# CPU
			cpu_data = state_meta.get("cpu", {})
			cpu_usage_ns = cpu_data.get("usage", 0)
			cpu_seconds = cpu_usage_ns / 1_000_000_000
			result["cpu_usage"] = min(round(cpu_seconds % 100, 1), 100)

			# Memory
			mem_data = state_meta.get("memory", {})
			mem_usage = mem_data.get("usage", 0)
			mem_total = mem_data.get("total", 0)
			result["memory_usage_bytes"] = mem_usage
			result["memory_total_bytes"] = mem_total
			if mem_total > 0:
				result["ram_usage"] = round((mem_usage / mem_total) * 100, 1)

			# Disk
			disk_data = state_meta.get("disk", {})
			root_disk = disk_data.get("root", {})
			disk_usage = root_disk.get("usage", 0)
			disk_total = root_disk.get("total", 0)
			result["disk_usage_bytes"] = disk_usage
			result["disk_total_bytes"] = disk_total
			if disk_total > 0:
				result["disk_usage"] = round((disk_usage / disk_total) * 100, 1)

			# Network
			network = state_meta.get("network", {})
			for iface_name, iface in network.items():
				if iface_name == "lo":
					continue
				counters = iface.get("counters", {})
				result["network_rx"] += counters.get("bytes_received", 0)
				result["network_tx"] += counters.get("bytes_sent", 0)

			result["connections"] = state_meta.get("processes", 0)
		except Exception:
			pass
	else:
		if cloud:
			result["ip_address"] = cloud.get("ip_address", "")

	return result


@frappe.whitelist()
def start_container(container_name, target_server=None):
	"""Start a container."""
	_check_admin_permission()

	if not target_server:
		frappe.throw("Server name is required")

	resp = _incus_api(target_server, "PUT", f"/1.0/instances/{container_name}/state", {
		"action": "start",
		"timeout": 30,
	})

	op = resp.get("operation")
	if op:
		_wait_for_operation(target_server, op)

	return {"status": "ok", "message": f"Container {container_name} started"}


@frappe.whitelist()
def stop_container(container_name, target_server=None):
	"""Stop a container."""
	_check_admin_permission()

	if not target_server:
		frappe.throw("Server name is required")

	resp = _incus_api(target_server, "PUT", f"/1.0/instances/{container_name}/state", {
		"action": "stop",
		"timeout": 30,
	})

	op = resp.get("operation")
	if op:
		_wait_for_operation(target_server, op)

	return {"status": "ok", "message": f"Container {container_name} stopped"}


@frappe.whitelist()
def restart_container(container_name, target_server=None):
	"""Restart a container."""
	_check_admin_permission()

	if not target_server:
		frappe.throw("Server name is required")

	resp = _incus_api(target_server, "PUT", f"/1.0/instances/{container_name}/state", {
		"action": "restart",
		"timeout": 30,
	})

	op = resp.get("operation")
	if op:
		_wait_for_operation(target_server, op)

	return {"status": "ok", "message": f"Container {container_name} restarted"}


@frappe.whitelist()
def create_container(container_name, image="alpine", container_type="container", target_server=None):
	"""Create a new container."""
	_check_admin_permission()

	if not target_server:
		frappe.throw("Server name is required")

	payload = {
		"name": container_name,
		"type": container_type,
		"source": {
			"type": "image",
			"alias": image,
		},
	}

	resp = _incus_api(target_server, "POST", "/1.0/instances", payload)

	op = resp.get("operation")
	if op:
		_wait_for_operation(target_server, op, timeout=120)

	# Auto-start the container
	try:
		start_resp = _incus_api(target_server, "PUT", f"/1.0/instances/{container_name}/state", {
			"action": "start",
			"timeout": 30,
		})
		op = start_resp.get("operation")
		if op:
			_wait_for_operation(target_server, op)
	except Exception:
		pass

	return {"status": "ok", "message": f"Container {container_name} created on {target_server}"}


@frappe.whitelist()
def delete_container(container_name, target_server=None):
	"""Delete a container."""
	_check_admin_permission()

	if not target_server:
		frappe.throw("Server name is required")

	# Stop first if running
	try:
		detail = _incus_api(target_server, "GET", f"/1.0/instances/{container_name}")
		if detail.get("metadata", {}).get("status") == "Running":
			stop_resp = _incus_api(target_server, "PUT", f"/1.0/instances/{container_name}/state", {
				"action": "stop",
				"timeout": 30,
				"force": True,
			})
			op = stop_resp.get("operation")
			if op:
				_wait_for_operation(target_server, op)
	except Exception:
		pass

	resp = _incus_api(target_server, "DELETE", f"/1.0/instances/{container_name}")

	op = resp.get("operation")
	if op:
		_wait_for_operation(target_server, op)

	return {"status": "ok", "message": f"Container {container_name} deleted"}


@frappe.whitelist()
def get_container_logs(container_name, target_server=None):
	"""Get container logs."""
	_check_admin_permission()

	if not target_server:
		return {"error": "Server name is required"}

	config = _get_server_config(target_server)

	try:
		resp = _incus_api(target_server, "GET", f"/1.0/instances/{container_name}/logs")
		log_urls = resp.get("metadata", [])

		logs = []
		for log_url in log_urls:
			log_name = log_url.rsplit("/", 1)[-1]
			if not log_name.endswith(".log"):
				continue
			try:
				r = requests.get(
					f"{config['url']}/1.0/instances/{container_name}/logs/{log_name}",
					cert=(config["cert"], config["key"]),
					verify=False,
					timeout=30,
				)
				r.raise_for_status()
				content = r.text
				for line in content.strip().split("\n")[-100:]:
					if not line.strip():
						continue
					level = "info"
					if "error" in line.lower() or "fail" in line.lower():
						level = "error"
					elif "warn" in line.lower():
						level = "warning"
					logs.append({
						"source": log_name,
						"level": level,
						"message": line.strip(),
						"timestamp": "",
					})
			except Exception:
				continue

		return logs
	except Exception as e:
		return [{"source": "system", "level": "error", "message": str(e), "timestamp": ""}]


@frappe.whitelist()
def get_snapshots(container_name, target_server=None):
	"""Get list of snapshots for a container."""
	_check_admin_permission()

	if not target_server:
		return []

	try:
		resp = _incus_api(target_server, "GET", f"/1.0/instances/{container_name}/snapshots?recursion=1")
		snapshots = []
		for snap in resp.get("metadata", []):
			snapshots.append({
				"name": snap.get("name", ""),
				"created_at": snap.get("created_at", ""),
				"stateful": snap.get("stateful", False),
				"size": snap.get("size", 0),
			})
		snapshots.sort(key=lambda s: s["created_at"], reverse=True)
		return snapshots
	except Exception:
		return []


@frappe.whitelist()
def create_snapshot(container_name, snapshot_name, stateful=False, target_server=None):
	"""Create a snapshot of a container."""
	_check_admin_permission()

	if not target_server:
		frappe.throw("Server name is required")

	if isinstance(stateful, str):
		stateful = stateful.lower() in ("true", "1")

	resp = _incus_api(target_server, "POST", f"/1.0/instances/{container_name}/snapshots", {
		"name": snapshot_name,
		"stateful": stateful,
	})

	op = resp.get("operation")
	if op:
		_wait_for_operation(target_server, op, timeout=120)

	return {"status": "ok", "message": f"Snapshot {snapshot_name} created"}


@frappe.whitelist()
def restore_snapshot(container_name, snapshot_name, target_server=None):
	"""Restore a container from a snapshot."""
	_check_admin_permission()

	if not target_server:
		frappe.throw("Server name is required")

	resp = _incus_api(target_server, "PUT", f"/1.0/instances/{container_name}", {
		"restore": snapshot_name,
	})

	op = resp.get("operation")
	if op:
		_wait_for_operation(target_server, op, timeout=120)

	return {"status": "ok", "message": f"Container restored from snapshot {snapshot_name}"}


@frappe.whitelist()
def delete_snapshot(container_name, snapshot_name, target_server=None):
	"""Delete a snapshot."""
	_check_admin_permission()

	if not target_server:
		frappe.throw("Server name is required")

	resp = _incus_api(target_server, "DELETE", f"/1.0/instances/{container_name}/snapshots/{snapshot_name}")

	op = resp.get("operation")
	if op:
		_wait_for_operation(target_server, op)

	return {"status": "ok", "message": f"Snapshot {snapshot_name} deleted"}


@frappe.whitelist()
def rebuild_container(container_name, image, target_server=None):
	"""Rebuild a container with a new image."""
	_check_admin_permission()

	if not target_server:
		frappe.throw("Server name is required")

	logs = []
	logs.append(f"=== Rebuild Container ===")
	logs.append(f"Container: {container_name}")
	logs.append(f"New image: {image}")
	logs.append(f"Server: {target_server}")

	try:
		detail = _incus_api(target_server, "GET", f"/1.0/instances/{container_name}")
		meta = detail.get("metadata", {})
		was_running = meta.get("status") == "Running"
		logs.append(f"Current status: {meta.get('status')}")

		if was_running:
			logs.append("Stopping container...")
			resp = _incus_api(target_server, "PUT", f"/1.0/instances/{container_name}/state", {
				"action": "stop",
				"timeout": 30,
				"force": True,
			})
			op = resp.get("operation")
			if op:
				_wait_for_operation(target_server, op)
			logs.append("✓ Container stopped")

		logs.append(f"Rebuilding with image '{image}'...")
		resp = _incus_api(target_server, "POST", f"/1.0/instances/{container_name}/rebuild", {
			"source": {
				"type": "image",
				"alias": image,
			},
		})
		op = resp.get("operation")
		if op:
			_wait_for_operation(target_server, op, timeout=300)
		logs.append("✓ Container rebuilt")

		if was_running:
			logs.append("Starting container...")
			resp = _incus_api(target_server, "PUT", f"/1.0/instances/{container_name}/state", {
				"action": "start",
				"timeout": 30,
			})
			op = resp.get("operation")
			if op:
				_wait_for_operation(target_server, op)
			logs.append("✓ Container started")

		logs.append("\n=== Rebuild completed successfully! ===")
		return {
			"success": True,
			"container_name": container_name,
			"image": image,
			"logs": logs,
			"message": f"Container '{container_name}' rebuilt with image '{image}'",
		}

	except Exception as e:
		logs.append(f"✗ Error: {str(e)}")
		return {
			"success": False,
			"error": str(e),
			"logs": logs,
			"message": f"Rebuild failed: {str(e)}",
		}


@frappe.whitelist()
def deploy_container_full(container_name, image="erp", pool_name="default", volumes_config=None, target_server=None):
	"""Full container deploy with volumes."""
	_check_admin_permission()

	if not target_server:
		frappe.throw("Server name is required")

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

	if not volumes_config:
		volumes_config = DEFAULT_VOLUMES

	logs = []
	current_step = 0
	tmp_mount_path = "/mnt/tmp"

	volumes_info = []
	for vol_config in volumes_config:
		volumes_info.append({
			"volume_name": f"{container_name}-{vol_config['name']}",
			"source_path": vol_config["source_path"],
			"device_name": vol_config["device_name"],
			"temp_device_name": f"tmp_{vol_config['name']}",
		})

	logs.append(f"=== Deploy Configuration ===")
	logs.append(f"Container: {container_name}")
	logs.append(f"Image: {image}")
	logs.append(f"Server: {target_server}")
	logs.append(f"Volumes: {len(volumes_info)}")

	try:
		# Step 1: Create container
		current_step = 1
		logs.append("Step 1: Creating container...")
		payload = {
			"name": container_name,
			"type": "container",
			"source": {"type": "image", "alias": image},
		}
		resp = _incus_api(target_server, "POST", "/1.0/instances", payload)
		op = resp.get("operation")
		if op:
			_wait_for_operation(target_server, op, timeout=120)
		logs.append(f"✓ Container '{container_name}' created")

		# Step 2: Start container
		current_step = 2
		logs.append("Step 2: Starting container...")
		resp = _incus_api(target_server, "PUT", f"/1.0/instances/{container_name}/state", {
			"action": "start", "timeout": 30,
		})
		op = resp.get("operation")
		if op:
			_wait_for_operation(target_server, op)
		time.sleep(3)
		logs.append(f"✓ Container '{container_name}' started")

		# Step 3: Create volumes
		current_step = 3
		logs.append(f"Step 3: Creating {len(volumes_info)} volume(s)...")
		for vol_info in volumes_info:
			try:
				_incus_api(target_server, "POST", f"/1.0/storage-pools/{pool_name}/volumes", {
					"name": vol_info["volume_name"],
					"type": "custom",
					"config": {},
				})
				logs.append(f"  ✓ Volume '{vol_info['volume_name']}' created")
			except Exception as e:
				if "409" in str(e):
					logs.append(f"  - Volume '{vol_info['volume_name']}' already exists")
				else:
					raise

		# Step 4: Temporarily mount volumes
		current_step = 4
		logs.append(f"Step 4: Mounting volumes temporarily...")
		for i, vol_info in enumerate(volumes_info):
			temp_path = f"{tmp_mount_path}{i+1}"
			vol_info["temp_path"] = temp_path
			temp_device_config = {
				"type": "disk",
				"pool": pool_name,
				"source": vol_info["volume_name"],
				"path": temp_path,
			}
			resp = _incus_api(target_server, "PATCH", f"/1.0/instances/{container_name}", {
				"devices": {vol_info["temp_device_name"]: temp_device_config},
			})
			op = resp.get("operation")
			if op:
				_wait_for_operation(target_server, op)
			logs.append(f"  ✓ Mounted at '{temp_path}'")
		time.sleep(2)

		# Step 5: Copy data
		current_step = 5
		logs.append(f"Step 5: Copying data to volumes...")
		for vol_info in volumes_info:
			exec_payload = {
				"command": ["cp", "-a", f"{vol_info['source_path']}/.", f"{vol_info['temp_path']}/"],
				"wait-for-websocket": False,
				"interactive": False,
			}
			try:
				resp = _incus_api(target_server, "POST", f"/1.0/instances/{container_name}/exec", exec_payload)
				op = resp.get("operation")
				if op:
					_wait_for_operation(target_server, op, timeout=120)
				logs.append(f"  ✓ Copied {vol_info['source_path']}")
			except Exception as e:
				logs.append(f"  - Warning copying {vol_info['source_path']}: {str(e)}")

		# Step 6: Unmount temporary volumes
		current_step = 6
		logs.append(f"Step 6: Unmounting temporary volumes...")
		current = _incus_api(target_server, "GET", f"/1.0/instances/{container_name}")
		current_meta = current.get("metadata", {})
		devices = current_meta.get("devices", {})
		for vol_info in volumes_info:
			devices.pop(vol_info["temp_device_name"], None)
		resp = _incus_api(target_server, "PUT", f"/1.0/instances/{container_name}", {
			"devices": devices,
			"config": current_meta.get("config", {}),
			"profiles": current_meta.get("profiles", []),
		})
		op = resp.get("operation")
		if op:
			_wait_for_operation(target_server, op)
		logs.append(f"✓ Temporary mounts removed")

		# Step 7: Stop container
		current_step = 7
		logs.append("Step 7: Stopping container...")
		resp = _incus_api(target_server, "PUT", f"/1.0/instances/{container_name}/state", {
			"action": "stop", "timeout": 30,
		})
		op = resp.get("operation")
		if op:
			_wait_for_operation(target_server, op)
		logs.append(f"✓ Container stopped")

		# Step 8: Mount volumes permanently
		current_step = 8
		logs.append(f"Step 8: Mounting volumes permanently...")
		for vol_info in volumes_info:
			permanent_device_config = {
				"type": "disk",
				"pool": pool_name,
				"source": vol_info["volume_name"],
				"path": vol_info["source_path"],
			}
			resp = _incus_api(target_server, "PATCH", f"/1.0/instances/{container_name}", {
				"devices": {vol_info["device_name"]: permanent_device_config},
			})
			op = resp.get("operation")
			if op:
				_wait_for_operation(target_server, op)
			logs.append(f"  ✓ {vol_info['volume_name']} → {vol_info['source_path']}")

		# Step 9: Start container
		current_step = 9
		logs.append("Step 9: Starting container (final)...")
		resp = _incus_api(target_server, "PUT", f"/1.0/instances/{container_name}/state", {
			"action": "start", "timeout": 30,
		})
		op = resp.get("operation")
		if op:
			_wait_for_operation(target_server, op)
		logs.append(f"✓ Container '{container_name}' started")

		logs.append("\n=== Deploy completed successfully! ===")
		return {
			"success": True,
			"container_name": container_name,
			"volumes": [v["volume_name"] for v in volumes_info],
			"logs": logs,
			"message": f"Container '{container_name}' deployed successfully",
		}

	except Exception as e:
		logs.append(f"✗ Error at step {current_step}: {str(e)}")
		return {
			"success": False,
			"step": current_step,
			"error": str(e),
			"logs": logs,
			"message": f"Deploy failed at step {current_step}: {str(e)}",
		}
