import logging
from typing import Optional, Any, Union

# noinspection PyUnresolvedReferences
from qgis.core import QgsLayerTreeGroup, QgsLayerTreeLayer, QgsProject
# noinspection PyUnresolvedReferences
from qgis.utils import iface

__all__ = ["duplicate_groups", "select_layer_in_group", "is_group_selected"]

from jord.qgis_utilities.helpers.copying import deepcopy_layer

try:
  from types import EllipsisType
except ImportError:
  EllipsisType = type(...)

logger = logging.getLogger(__name__)


def duplicate_groups(
    group_to_duplicate,
    *,
    group_parent: Optional[Any] = None,
    new_name: Union[str, EllipsisType, None] = None,
) -> QgsLayerTreeGroup:
  if group_to_duplicate is None:
    logger.error("Group was None")
    return

  logger.info(f"Duplicating {group_to_duplicate.name()}")

  if new_name is ... or new_name == "" or new_name is None:
    new_name = f"{group_to_duplicate.name()} (Copy)"

  sub_items = []
  assert (
      group_to_duplicate is not None
  ), f"{group_to_duplicate=} is required to create a duplicate group"

  if group_parent is None:
    group_parent = group_to_duplicate.parent()

  if group_parent is None:
    raise ValueError(f"Group parent was not found for {group_to_duplicate}")

  new_group_parent = group_parent.addGroup(new_name)
  for original_group_child in group_to_duplicate.children():
    if isinstance(original_group_child, QgsLayerTreeGroup):
      new_sub_group, sub_sub_items = duplicate_groups(
        original_group_child, group_parent=new_group_parent, new_name=...
      )
      sub_items.extend([new_sub_group, *sub_sub_items])
    elif isinstance(original_group_child, QgsLayerTreeLayer):
      sub_items.append(
        duplicate_tree_node(new_group_parent, original_group_child)
      )
    else:
      logger.error(f"{original_group_child} no supported in duplication")

  return new_group_parent, sub_items


def duplicate_tree_node(new_group_parent, original_group_child):
  original_layer = original_group_child.layer()
  new_layer_copy = deepcopy_layer(original_layer)
  QgsProject.instance().addMapLayer(new_layer_copy, False)

  if False:
    new_layer_tree_node = QgsLayerTreeLayer(
      new_layer_copy
    )  # WORKS BUT MISSING STYLING
    new_group_parent.addChildNode(new_layer_tree_node)
  elif False:
    # Does not WORK EITHER
    new_layer_tree_node = QgsLayerTreeLayer(
      new_layer_copy.id(),
      original_layer.name(),
      new_layer_copy.source(),
      original_layer.providerType(),
    )
  elif False:
    # THIS DOES NOT WORK!!!
    new_layer_tree_node = (
      original_group_child.clone()
    )  # THIS JUST CREATES NEW VIEW of the same data!!!!
    new_layer_tree_node.layer().setDataSource(
      new_layer_copy.source(),
      new_layer_copy.name(),
      new_layer_copy.providerType(),
    )
  elif True:
    new_group_parent.insertLayer(0, new_layer_copy)
  else:
    raise Exception()

  return new_layer_copy


def select_layer_in_group(layer_name, group_name):
  group = QgsProject.instance().layerTreeRoot().findGroup(group_name)
  if group is not None:
    for child in group.children():
      if child.name() == layer_name:
        iface.setActiveLayer(child.layer())


def is_group_selected(group_name):
  group = QgsProject.instance().layerTreeRoot().findGroup(group_name)
  return group in iface.layerTreeView().selectedNodes()
