/** @file
  Unicode Collation Support component that hides the trivial difference of Unicode Collation
  and Unicode collation 2 Protocol.

  Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
  This program and the accompanying materials are licensed and made available
under the terms and conditions of the BSD License which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php

THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

**/

#include "Fat.h"

EFI_UNICODE_COLLATION_PROTOCOL  *mUnicodeCollationInterface = NULL;

/**
  Worker function to initialize Unicode Collation support.

  It tries to locate Unicode Collation (2) protocol and matches it with current
  platform language code.

  @param  AgentHandle          The handle used to open Unicode Collation (2) protocol.
  @param  ProtocolGuid         The pointer to Unicode Collation (2) protocol GUID.
  @param  VariableName         The name of the RFC 4646 or ISO 639-2 language variable.
  @param  DefaultLanguage      The default language in case the RFC 4646 or ISO 639-2 language is absent.

  @retval EFI_SUCCESS          The Unicode Collation (2) protocol has been successfully located.
  @retval Others               The Unicode Collation (2) protocol has not been located.

**/
EFI_STATUS
InitializeUnicodeCollationSupportWorker (
  IN EFI_HANDLE         AgentHandle,
  IN EFI_GUID           *ProtocolGuid,
  IN CONST CHAR16       *VariableName,
  IN CONST CHAR8        *DefaultLanguage
  )
{
  EFI_STATUS                      ReturnStatus;
  EFI_STATUS                      Status;
  UINTN                           NumHandles;
  UINTN                           Index;
  EFI_HANDLE                      *Handles;
  EFI_UNICODE_COLLATION_PROTOCOL  *Uci;
  BOOLEAN                         Iso639Language;
  CHAR8                           *Language;
  CHAR8                           *BestLanguage;

  Status = gBS->LocateHandleBuffer (
                  ByProtocol,
                  ProtocolGuid,
                  NULL,
                  &NumHandles,
                  &Handles
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  Iso639Language = (BOOLEAN) (ProtocolGuid == &gEfiUnicodeCollationProtocolGuid);
  GetEfiGlobalVariable2 (VariableName, (VOID**) &Language, NULL);

  ReturnStatus = EFI_UNSUPPORTED;
  for (Index = 0; Index < NumHandles; Index++) {
    //
    // Open Unicode Collation Protocol
    //
    Status = gBS->OpenProtocol (
                    Handles[Index],
                    ProtocolGuid,
                    (VOID **) &Uci,
                    AgentHandle,
                    NULL,
                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
                    );
    if (EFI_ERROR (Status)) {
      continue;
    }

    //
    // Find the best matching matching language from the supported languages
    // of Unicode Collation (2) protocol. 
    //
    BestLanguage = GetBestLanguage (
                     Uci->SupportedLanguages,
                     Iso639Language,
                     (Language == NULL) ? "" : Language,
                     DefaultLanguage,
                     NULL
                     );
    if (BestLanguage != NULL) {
      FreePool (BestLanguage);
      mUnicodeCollationInterface = Uci;
      ReturnStatus = EFI_SUCCESS;
      break;
    }
  }

  if (Language != NULL) {
    FreePool (Language);
  }

  FreePool (Handles);

  return ReturnStatus;
}

/**
  Initialize Unicode Collation support.

  It tries to locate Unicode Collation 2 protocol and matches it with current
  platform language code. If for any reason the first attempt fails, it then tries to
  use Unicode Collation Protocol.

  @param  AgentHandle          The handle used to open Unicode Collation (2) protocol.

  @retval EFI_SUCCESS          The Unicode Collation (2) protocol has been successfully located.
  @retval Others               The Unicode Collation (2) protocol has not been located.

**/
EFI_STATUS
InitializeUnicodeCollationSupport (
  IN EFI_HANDLE    AgentHandle
  )
{

  EFI_STATUS       Status;

  Status = EFI_UNSUPPORTED;

  //
  // First try to use RFC 4646 Unicode Collation 2 Protocol.
  //
  Status = InitializeUnicodeCollationSupportWorker (
             AgentHandle,
             &gEfiUnicodeCollation2ProtocolGuid,
             L"PlatformLang",
             (CONST CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang)
             );
  //
  // If the attempt to use Unicode Collation 2 Protocol fails, then we fall back
  // on the ISO 639-2 Unicode Collation Protocol.
  //
  if (EFI_ERROR (Status)) {
    Status = InitializeUnicodeCollationSupportWorker (
               AgentHandle,
               &gEfiUnicodeCollationProtocolGuid,
               L"Lang",
               (CONST CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultLang)
               );
  }

  return Status;
}


/**
  Performs a case-insensitive comparison of two Null-terminated Unicode strings.

  @param  S1                   A pointer to a Null-terminated Unicode string.
  @param  S2                   A pointer to a Null-terminated Unicode string.

  @retval 0                    S1 is equivalent to S2.
  @retval >0                   S1 is lexically greater than S2.
  @retval <0                   S1 is lexically less than S2.
**/
INTN
FatStriCmp (
  IN CHAR16       *S1,
  IN CHAR16       *S2
  )
{
  ASSERT (StrSize (S1) != 0);
  ASSERT (StrSize (S2) != 0);
  ASSERT (mUnicodeCollationInterface != NULL);

  return mUnicodeCollationInterface->StriColl (
                                       mUnicodeCollationInterface,
                                       S1,
                                       S2
                                       );
}


/**
  Uppercase a string.

  @param  String                   The string which will be upper-cased.


**/
VOID
FatStrUpr (
  IN OUT CHAR16   *String
  )
{
  ASSERT (StrSize (String) != 0);
  ASSERT (mUnicodeCollationInterface != NULL);

  mUnicodeCollationInterface->StrUpr (mUnicodeCollationInterface, String);
}


/**
  Lowercase a string

  @param  String                   The string which will be lower-cased.


**/
VOID
FatStrLwr (
  IN OUT CHAR16   *String
  )
{
  ASSERT (StrSize (String) != 0);
  ASSERT (mUnicodeCollationInterface != NULL);

  mUnicodeCollationInterface->StrLwr (mUnicodeCollationInterface, String);
}


/**
  Convert FAT string to unicode string.

  @param  FatSize               The size of FAT string.
  @param  Fat                   The FAT string.
  @param  String                The unicode string.

  @return None.

**/
VOID
FatFatToStr (
  IN  UINTN                            FatSize,
  IN  CHAR8                            *Fat,
  OUT CHAR16                           *String
  )
{
  ASSERT (Fat != NULL);
  ASSERT (String != NULL);
  ASSERT (((UINTN) String & 0x01) == 0);
  ASSERT (mUnicodeCollationInterface != NULL);

  mUnicodeCollationInterface->FatToStr (mUnicodeCollationInterface, FatSize, Fat, String);
}


/**
  Convert unicode string to Fat string.

  @param  String                The unicode string.
  @param  FatSize               The size of the FAT string.
  @param  Fat                   The FAT string.

  @retval TRUE                  Convert successfully.
  @retval FALSE                 Convert error.

**/
BOOLEAN
FatStrToFat (
  IN  CHAR16                          *String,
  IN  UINTN                           FatSize,
  OUT CHAR8                           *Fat
  )
{
  ASSERT (Fat != NULL);
  ASSERT (StrSize (String) != 0);
  ASSERT (mUnicodeCollationInterface != NULL);

  return mUnicodeCollationInterface->StrToFat (
                                       mUnicodeCollationInterface,
                                       String,
                                       FatSize,
                                       Fat
                                       );
}
