/** @file
  Implementation of translation upon VT-UTF8.

Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#include "Terminal.h"

/**
  Translate all VT-UTF8 characters in the Raw FIFI into unicode characters,
  and insert them into Unicode FIFO.

  @param TerminalDevice          The terminal device.

**/
VOID
VTUTF8RawDataToUnicode (
  IN  TERMINAL_DEV  *TerminalDevice
  )
{
  UTF8_CHAR  Utf8Char;
  UINT8      ValidBytes;
  UINT16     UnicodeChar;

  ValidBytes = 0;
  //
  // pop the raw data out from the raw fifo,
  // and translate it into unicode, then push
  // the unicode into unicode fifo, until the raw fifo is empty.
  //
  while (!IsRawFiFoEmpty (TerminalDevice) && !IsUnicodeFiFoFull (TerminalDevice)) {
    GetOneValidUtf8Char (TerminalDevice, &Utf8Char, &ValidBytes);

    if ((ValidBytes < 1) || (ValidBytes > 3)) {
      continue;
    }

    Utf8ToUnicode (Utf8Char, ValidBytes, (CHAR16 *)&UnicodeChar);

    UnicodeFiFoInsertOneKey (TerminalDevice, UnicodeChar);
  }
}

/**
  Get one valid VT-UTF8 characters set from Raw Data FIFO.

  @param  Utf8Device          The terminal device.
  @param  Utf8Char            Returned valid VT-UTF8 characters set.
  @param  ValidBytes          The count of returned VT-VTF8 characters.
                              If ValidBytes is zero, no valid VT-UTF8 returned.

**/
VOID
GetOneValidUtf8Char (
  IN  TERMINAL_DEV  *Utf8Device,
  OUT UTF8_CHAR     *Utf8Char,
  OUT UINT8         *ValidBytes
  )
{
  UINT8    Temp;
  UINT8    Index;
  BOOLEAN  FetchFlag;

  Temp      = 0;
  Index     = 0;
  FetchFlag = TRUE;

  //
  // if no valid Utf8 char is found in the RawFiFo,
  // then *ValidBytes will be zero.
  //
  *ValidBytes = 0;

  while (!IsRawFiFoEmpty (Utf8Device)) {
    RawFiFoRemoveOneKey (Utf8Device, &Temp);

    switch (*ValidBytes) {
      case 0:
        if ((Temp & 0x80) == 0) {
          //
          // one-byte utf8 char
          //
          *ValidBytes = 1;

          Utf8Char->Utf8_1 = Temp;

          FetchFlag = FALSE;
        } else if ((Temp & 0xe0) == 0xc0) {
          //
          // two-byte utf8 char
          //
          *ValidBytes = 2;

          Utf8Char->Utf8_2[1] = Temp;
        } else if ((Temp & 0xf0) == 0xe0) {
          //
          // three-byte utf8 char
          //
          *ValidBytes = 3;

          Utf8Char->Utf8_3[2] = Temp;

          Index++;
        } else {
          //
          // reset *ValidBytes to zero, let valid utf8 char search restart
          //
          *ValidBytes = 0;
        }

        break;

      case 2:
        //
        // two-byte utf8 char go on
        //
        if ((Temp & 0xc0) == 0x80) {
          Utf8Char->Utf8_2[0] = Temp;

          FetchFlag = FALSE;
        } else {
          *ValidBytes = 0;
        }

        break;

      case 3:
        //
        // three-byte utf8 char go on
        //
        if ((Temp & 0xc0) == 0x80) {
          if (Index == 1) {
            Utf8Char->Utf8_3[1] = Temp;
            Index++;
          } else {
            Utf8Char->Utf8_3[0] = Temp;
            FetchFlag           = FALSE;
          }
        } else {
          //
          // reset *ValidBytes and Index to zero, let valid utf8 char search restart
          //
          *ValidBytes = 0;
          Index       = 0;
        }

        break;

      default:
        break;
    }

    if (!FetchFlag) {
      break;
    }
  }

  return;
}

/**
  Translate VT-UTF8 characters into one Unicode character.

  UTF8 Encoding Table
  Bits per Character | Unicode Character Range | Unicode Binary  Encoding |  UTF8 Binary Encoding
        0-7           |     0x0000 - 0x007F     |     00000000 0xxxxxxx    |   0xxxxxxx
        8-11          |     0x0080 - 0x07FF     |     00000xxx xxxxxxxx     |   110xxxxx 10xxxxxx
       12-16         |     0x0800 - 0xFFFF     |     xxxxxxxx xxxxxxxx    |   1110xxxx 10xxxxxx 10xxxxxx


  @param  Utf8Char         VT-UTF8 character set needs translating.
  @param  ValidBytes       The count of valid VT-UTF8 characters.
  @param  UnicodeChar      Returned unicode character.

**/
VOID
Utf8ToUnicode (
  IN  UTF8_CHAR  Utf8Char,
  IN  UINT8      ValidBytes,
  OUT CHAR16     *UnicodeChar
  )
{
  UINT8  UnicodeByte0;
  UINT8  UnicodeByte1;
  UINT8  Byte0;
  UINT8  Byte1;
  UINT8  Byte2;

  *UnicodeChar = 0;

  //
  // translate utf8 code to unicode, in terminal standard,
  // up to 3 bytes utf8 code is supported.
  //
  switch (ValidBytes) {
    case 1:
      //
      // one-byte utf8 code
      //
      *UnicodeChar = (UINT16)Utf8Char.Utf8_1;
      break;

    case 2:
      //
      // two-byte utf8 code
      //
      Byte0 = Utf8Char.Utf8_2[0];
      Byte1 = Utf8Char.Utf8_2[1];

      UnicodeByte0 = (UINT8)((Byte1 << 6) | (Byte0 & 0x3f));
      UnicodeByte1 = (UINT8)((Byte1 >> 2) & 0x07);
      *UnicodeChar = (UINT16)(UnicodeByte0 | (UnicodeByte1 << 8));
      break;

    case 3:
      //
      // three-byte utf8 code
      //
      Byte0 = Utf8Char.Utf8_3[0];
      Byte1 = Utf8Char.Utf8_3[1];
      Byte2 = Utf8Char.Utf8_3[2];

      UnicodeByte0 = (UINT8)((Byte1 << 6) | (Byte0 & 0x3f));
      UnicodeByte1 = (UINT8)((Byte2 << 4) | ((Byte1 >> 2) & 0x0f));
      *UnicodeChar = (UINT16)(UnicodeByte0 | (UnicodeByte1 << 8));

    default:
      break;
  }

  return;
}

/**
  Translate one Unicode character into VT-UTF8 characters.

  UTF8 Encoding Table
  Bits per Character | Unicode Character Range | Unicode Binary  Encoding |  UTF8 Binary Encoding
        0-7           |     0x0000 - 0x007F     |     00000000 0xxxxxxx    |   0xxxxxxx
        8-11          |     0x0080 - 0x07FF     |     00000xxx xxxxxxxx     |   110xxxxx 10xxxxxx
       12-16         |     0x0800 - 0xFFFF     |     xxxxxxxx xxxxxxxx    |   1110xxxx 10xxxxxx 10xxxxxx


  @param  Unicode          Unicode character need translating.
  @param  Utf8Char         Return VT-UTF8 character set.
  @param  ValidBytes       The count of valid VT-UTF8 characters. If
                           ValidBytes is zero, no valid VT-UTF8 returned.

**/
VOID
UnicodeToUtf8 (
  IN  CHAR16     Unicode,
  OUT UTF8_CHAR  *Utf8Char,
  OUT UINT8      *ValidBytes
  )
{
  UINT8  UnicodeByte0;
  UINT8  UnicodeByte1;

  //
  // translate unicode to utf8 code
  //
  UnicodeByte0 = (UINT8)Unicode;
  UnicodeByte1 = (UINT8)(Unicode >> 8);

  if (Unicode < 0x0080) {
    Utf8Char->Utf8_1 = (UINT8)(UnicodeByte0 & 0x7f);
    *ValidBytes      = 1;
  } else if (Unicode < 0x0800) {
    //
    // byte sequence: high -> low
    //                Utf8_2[0], Utf8_2[1]
    //
    Utf8Char->Utf8_2[1] = (UINT8)((UnicodeByte0 & 0x3f) + 0x80);
    Utf8Char->Utf8_2[0] = (UINT8)((((UnicodeByte1 << 2) + (UnicodeByte0 >> 6)) & 0x1f) + 0xc0);

    *ValidBytes = 2;
  } else {
    //
    // byte sequence: high -> low
    //                Utf8_3[0], Utf8_3[1], Utf8_3[2]
    //
    Utf8Char->Utf8_3[2] = (UINT8)((UnicodeByte0 & 0x3f) + 0x80);
    Utf8Char->Utf8_3[1] = (UINT8)((((UnicodeByte1 << 2) + (UnicodeByte0 >> 6)) & 0x3f) + 0x80);
    Utf8Char->Utf8_3[0] = (UINT8)(((UnicodeByte1 >> 4) & 0x0f) + 0xe0);

    *ValidBytes = 3;
  }
}

/**
  Check if input string is valid VT-UTF8 string.

  @param  TerminalDevice          The terminal device.
  @param  WString                 The input string.

  @retval EFI_SUCCESS             If all input characters are valid.

**/
EFI_STATUS
VTUTF8TestString (
  IN  TERMINAL_DEV  *TerminalDevice,
  IN  CHAR16        *WString
  )
{
  //
  // to utf8, all kind of characters are supported.
  //
  return EFI_SUCCESS;
}
