/**************************************************************************//**
 * @brief Draws the graphics on the display
 * @version 4.2.1
 ******************************************************************************
 * @section License
 * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
 *******************************************************************************
 *
 * This file is licensed under the Silabs License Agreement. See the file
 * "Silabs_License_Agreement.txt" for details. Before using this software for
 * any purpose, you must agree to the terms of that agreement.
 *
 ******************************************************************************/

#include "graphics.h"
#include "em_types.h"
#include "glib.h"
#include "dmd.h"
#include "display.h"
#include "textdisplay.h"
#include "retargettextdisplay.h"
#include "background.h"
#include <string.h>
#include <stdio.h>
#include "rtcdriver.h"

static GLIB_Context_t glibContext;          /* Global glib context */

static void GRAPHICS_DrawBackground(int xoffset);


/**************************************************************************//**
 * @brief Initializes the graphics stack.
 * @note This function will /hang/ if errors occur (usually
 *       caused by faulty displays.
 *****************************************************************************/
void GRAPHICS_Init(void)
{
  EMSTATUS status;

  /* Initialize the display module. */
  status = DISPLAY_Init();
  if (DISPLAY_EMSTATUS_OK != status)
    while (1)
      ;

  /* Initialize the DMD module for the DISPLAY device driver. */
  status = DMD_init(0);
  if (DMD_OK != status)
    while (1)
      ;

  status = GLIB_contextInit(&glibContext);
  if (GLIB_OK != status)
    while (1)
      ;

  glibContext.backgroundColor = Black;
  glibContext.foregroundColor = White;

  /* Use Narrow font */
  GLIB_setFont(&glibContext, (GLIB_Font_t *)&GLIB_FontNarrow6x8);
}


/**************************************************************************//**
 * @brief Draws the background image
 * @param xoffset
 *        The background image is wider than the display. This parameter
 *        selects which part to show. The offset is given in multiples of 8.
 *        If you increase xoffset by 1, the background will be shifted by 8
 *        pixels
 *****************************************************************************/
static void GRAPHICS_DrawBackground(int xoffset)
{
  EMSTATUS status;
  int      y;
  int      img;
  int      size;

  if (xoffset < 0)
  {
    size = -xoffset * 8;
  }
  else
  {
    size = 128;
  }


  for (y = 0; y < 128; y++)
  {
    /* Write bitmap to display */
    img = xoffset + y * (BACKGROUND_XSIZE / 8);
    if (xoffset < 0)
      img = (XOFFSET_END + xoffset) + y * (BACKGROUND_XSIZE / 8);

    status = DMD_writeData(0, y,
                           background + img,
                           size);

    img = y * (BACKGROUND_XSIZE / 8);

    if (size != 128)
      status |= DMD_writeData(size, y,
                              background + img,
                              128 - size);
    if (status != DMD_OK)
    {
      while (1)
        ;
    }
  }
}


/**************************************************************************//**
 * @brief Draws the initial graphic
 * @param demo_version
 *        The version number of the HRM/SpO2 demo
 *
 * @param sihrmVersion
 *        The version number of the algorithm
 *****************************************************************************/
void GRAPHICS_DrawInit (char *demo_version, char *sihrmVersion)
{
  GLIB_clear(&glibContext);

  GRAPHICS_DrawBackground(64);

  GLIB_setFont(&glibContext, (GLIB_Font_t *) &GLIB_FontNormal8x8);
  GLIB_drawString(&glibContext, demo_version, 16, 5, 95, 0);
  GLIB_drawString(&glibContext, sihrmVersion, 16, 5, 105, 0);

  DMD_updateDisplay();

}

/**************************************************************************//**
 * @brief Draws the error graphic
 *****************************************************************************/
void GRAPHICS_DrawError ( void )
{
  GLIB_clear(&glibContext);

  GRAPHICS_DrawBackground(64);

  GLIB_setFont(&glibContext, (GLIB_Font_t *) &GLIB_FontNormal8x8);
  GLIB_drawString(&glibContext, "System Error", 16, 5, 85, 0);

  DMD_updateDisplay();

}

/**************************************************************************//**
 * @brief Draws the HRM display graphic
 * @param displayHeartRateValue
 *        The heart rate value to display
 *
 * @param displayStatus
 *        The status of the HRM/SpO2 algorithm result
 *
 * @param hrValid
 *        Heart rate result is valid or not
 *****************************************************************************/
void GRAPHICS_DrawHrm(int16_t displayHeartRateValue, int16_t displayStatus, int16_t hrValid)
{
  char stringHR[10];

  int16_t hr_data = displayHeartRateValue;

  GLIB_clear(&glibContext);

  GRAPHICS_DrawBackground(0);

  GLIB_setFont(&glibContext, (GLIB_Font_t *) &GLIB_FontNormal8x8);
  /* Draw data */
  if (hrValid && (hr_data!=0))
  {
    snprintf(stringHR, 10, "%d", (int) hr_data);
    GLIB_setFont(&glibContext, (GLIB_Font_t *) &GLIB_FontNumber16x20);
    GLIB_drawString(&glibContext, stringHR, 3, 31, 30, 0);
  }
  else if ((hrValid == false) || (hr_data == 0))
  {
    GLIB_drawString(&glibContext, "Acquiring", 9, 45, 96, 0);
  }

  DMD_updateDisplay();
}

/**************************************************************************//**
 * @brief Draws the SpO2 display graphic
 * @param displaySpO2Value
 *        The SpO2 value to display
 *
 * @param displayStatus
 *        The status of the HRM/SpO2 algorithm result
 *
 * @param spo2Valid
 *        SpO2 result is valid or not
 *****************************************************************************/
void GRAPHICS_DrawSpO2(int16_t displaySpO2Value, int16_t displayStatus, int16_t spo2Valid)
{
  char stringSpO2[10];

  int16_t spo2_data = displaySpO2Value;

  GLIB_clear(&glibContext);

  GRAPHICS_DrawBackground(256);
  GLIB_setFont(&glibContext, (GLIB_Font_t *) &GLIB_FontNormal8x8);
  /* Draw data */
  if (spo2Valid && (spo2_data!=0))
  {
    snprintf(stringSpO2, 10, "%d", (int) spo2_data);
    GLIB_setFont(&glibContext, (GLIB_Font_t *) &GLIB_FontNumber16x20);
    GLIB_drawString(&glibContext, stringSpO2, 3, 31, 30, 0);
  }
  else if ((spo2Valid == false) || (spo2_data == 0))
  {
    GLIB_drawString(&glibContext, "Acquiring", 9, 45, 96, 0);
  }

  DMD_updateDisplay();
}

/**************************************************************************//**
 * @brief Draws the idle graphic
 *****************************************************************************/
void GRAPHICS_DrawIdle(void)
{
  GLIB_clear(&glibContext);

  GRAPHICS_DrawBackground(0);
  GLIB_setFont(&glibContext, (GLIB_Font_t *) &GLIB_FontNormal8x8);
  GLIB_drawString(&glibContext, "Idle", 9, 45, 96, 0);

  DMD_updateDisplay();
}



