/** @file
  Metadata Proximity Domain handlers.

  Copyright (c) 2025, Arm Limited. All rights reserved.
  SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#include <Base.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <ConfigurationManagerObject.h>

#include <Library/MetadataObjLib.h>
#include "MetadataHandler.h"

/** Uid Entry

  One entry is allocated for each HID/CID/EISAID. Each entry
  contains a counter used for the generation of UID values.
**/
typedef struct MetadataUidEntry {
  LIST_ENTRY    List;

  /// _HID or _CID of the device (NULL-terminated string).
  /// This provides a mean to uniquely identify a device type.
  /// If not populated, EisaId must be set.
  CHAR8         NameId[9];

  /// EisaId of the device.
  /// This provides a mean to uniquely identify a device type.
  /// If not populated, NameId must be set.
  UINT32        EisaId;

  /// Current Id used for the generation of a HID/CID/EisaId.
  UINT32        CurrId;
} METADATA_UID_ENTRY;

// List of METADATA_UID_ENTRY
STATIC LIST_ENTRY  mUidList = INITIALIZE_LIST_HEAD_VARIABLE (mUidList);

/** Allocate a METADATA_UID_ENTRY.

  @param [in]  Metadata   Metadata containing the NameId/EisaId to use.
  @param [out] OutEntry   Allocated Entry.

  @retval EFI_SUCCESS           Success.
  @retval EFI_INVALID_PARAMETER A parameter is invalid.
  @retval EFI_OUT_OF_RESOURCES  Out of resources.
**/
STATIC
EFI_STATUS
EFIAPI
AllocateUidEntry (
  IN   METADATA_OBJ_UID   *Metadata,
  OUT METADATA_UID_ENTRY  **OutEntry
  )
{
  METADATA_UID_ENTRY  *Entry;

  if ((Metadata == NULL) || (OutEntry == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  Entry = AllocateZeroPool (sizeof (METADATA_UID_ENTRY));
  if (Entry == NULL) {
    ASSERT (Entry != NULL);
    return EFI_OUT_OF_RESOURCES;
  }

  InitializeListHead (&Entry->List);
  Entry->CurrId = 0;

  if (Metadata->NameId[0] != 0) {
    AsciiStrCpyS (Entry->NameId, sizeof (Metadata->NameId), Metadata->NameId);
  } else {
    Entry->EisaId = Metadata->EisaId;
  }

  *OutEntry = Entry;
  return EFI_SUCCESS;
}

/** Find a matching METADATA_UID_ENTRY.
    If no Entry is found, allocate one.

  @param [in]  Metadata   Metadata containing the NameId/EisaId to search.
  @param [out] OutEntry   Matching or allocated Entry.

  @retval EFI_SUCCESS           Success.
  @retval EFI_INVALID_PARAMETER A parameter is invalid.
  @retval EFI_OUT_OF_RESOURCES  Out of resources.
**/
STATIC
EFI_STATUS
EFIAPI
FindEntry (
  IN   METADATA_OBJ_UID   *Metadata,
  OUT METADATA_UID_ENTRY  **OutEntry
  )
{
  EFI_STATUS          Status;
  LIST_ENTRY          *Link;
  METADATA_UID_ENTRY  *Entry;

  if ((Metadata == NULL) || (OutEntry == NULL)) {
    ASSERT (Metadata != NULL);
    ASSERT (OutEntry != NULL);
    return EFI_INVALID_PARAMETER;
  }

  Link = GetNextNode (&mUidList, &mUidList);

  while (Link != &mUidList) {
    Entry = (METADATA_UID_ENTRY *)Link;

    if (Entry->NameId[0] != 0) {
      if (AsciiStrnCmp (Entry->NameId, Metadata->NameId, sizeof (Metadata->NameId)) == 0) {
        break;
      }
    } else if (Metadata->EisaId != 0) {
      if (Entry->EisaId == Metadata->EisaId) {
        break;
      }
    } else {
      DEBUG ((DEBUG_ERROR, "MetadatUid: Empty NameId and EisaId\n"));
      ASSERT (0);
      return EFI_INVALID_PARAMETER;
    }

    Link = GetNextNode (&mUidList, Link);
  } // while

  // No matching METADATA_UID_ENTRY found.
  if (Link == &mUidList) {
    Status = AllocateUidEntry (Metadata, &Entry);
    if (EFI_ERROR (Status)) {
      ASSERT_EFI_ERROR (Status);
      return Status;
    }

    InsertTailList (&mUidList, &Entry->List);
  }

  *OutEntry = Entry;
  return EFI_SUCCESS;
}

/** Query the MetadataObjLib for metadata matching the input (Type/Token).
    If the metadata exists, return it.
    Otherwise:
    - Generate a new metadata object
    - Add it to the MetadataObjLib
    - return it

  @param[in]       Root          Root of the Metadata information.
  @param[in]       Type            METADATA_TYPE of the entry to generate.
  @param[in]       Token         Token uniquely identifying an entry among other
                                 objects with the input METADATA_TYPE.
  @param[in]       Context       Optional context to use during the Metadata generation.
  @param[in, out]  Metadata      On input, can contain METADATA_TYPE-specific information.
                                 On output and if success, contains the generated
                                 Metadata object.
  @param[in]       MetadataSize  Size of the input Metadata.

  @retval EFI_SUCCESS           Success.
  @retval EFI_INVALID_PARAMETER A parameter is invalid.
**/
EFI_STATUS
EFIAPI
MetadataGenerateUid (
  IN      METADATA_ROOT_HANDLE  Root,
  IN      METADATA_TYPE         Type,
  IN      CM_OBJECT_TOKEN       Token,
  IN      VOID                  *Context,
  IN OUT  VOID                  *Metadata,
  IN      UINT32                MetadataSize
  )
{
  EFI_STATUS          Status;
  METADATA_OBJ_UID    *Uid;
  METADATA_UID_ENTRY  *Entry;

  if ((Type != MetadataTypeUid) ||
      (Token == CM_NULL_TOKEN)  ||
      (Metadata == NULL))
  {
    ASSERT (Type == MetadataTypeUid);
    ASSERT (Token != CM_NULL_TOKEN);
    ASSERT (Metadata != NULL);
    return EFI_INVALID_PARAMETER;
  }

  Status = MetadataGet (Root, Type, Token, Metadata, MetadataSize);
  if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
    ASSERT_EFI_ERROR (Status);
    return Status;
  } else if (Status == EFI_SUCCESS) {
    // Metadata for this (Type/Token) already exists.
    return EFI_SUCCESS;
  }

  // Generate new Metadata (i.e. Status == EFI_NOT_FOUND).

  // Get the Current Type for this HID/CID/EISAID
  Status = FindEntry (Metadata, &Entry);
  if (EFI_ERROR (Status)) {
    ASSERT_EFI_ERROR (Status);
    return Status;
  }

  Uid      = (METADATA_OBJ_UID *)Metadata;
  Uid->Uid = Entry->CurrId++;

  Status = MetadataAdd (Root, Type, Token, Metadata, MetadataSize);
  if (EFI_ERROR (Status)) {
    ASSERT_EFI_ERROR (Status);
    return Status;
  }

  return EFI_SUCCESS;
}

/** Validate the Metadata.

  @param[in]  Root    Root of the Metadata information.

  @retval EFI_SUCCESS           Success.
  @retval EFI_INVALID_PARAMETER A parameter is invalid.
**/
EFI_STATUS
EFIAPI
MetadataValidateUid (
  IN  METADATA_ROOT_HANDLE  Root
  )
{
  METADATA_HANDLE   Handle0;
  METADATA_HANDLE   Handle1;
  METADATA_OBJ_UID  Metadata0;
  METADATA_OBJ_UID  Metadata1;

  Handle0 = NULL;

  while (TRUE) {
    Handle0 = MetadataIterate (
                Root,
                MetadataTypeUid,
                Handle0,
                &Metadata0,
                sizeof (METADATA_OBJ_UID)
                );
    if (Handle0 == NULL) {
      break;
    }

    // Loop starting from Handle0
    Handle1 = Handle0;

    while (TRUE) {
      Handle1 = MetadataIterate (
                  Root,
                  MetadataTypeUid,
                  Handle1,
                  &Metadata1,
                  sizeof (METADATA_OBJ_UID)
                  );

      if (Handle1 == NULL) {
        break;
      }

      if (CompareMem (&Metadata0, &Metadata1, sizeof (METADATA_OBJ_UID)) == 0) {
        DEBUG ((
          DEBUG_ERROR,
          "Metadata: Uid: Same Type: EisaId=%d NameId=%a Uid=%d \n",
          Metadata0.EisaId,
          Metadata0.NameId,
          Metadata0.Uid
          ));
        ASSERT (0);
      }
    }
  }

  return EFI_SUCCESS;
}
