/*
 *  Copyright 1994-2022 Olivier Girondel
 *
 *  This file is part of lebiniou.
 *
 *  lebiniou is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  lebiniou is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with lebiniou. If not, see <http://www.gnu.org/licenses/>.
 */

#include <SDL2/SDL_ttf.h>
#include "ttf.h"

#define OSD_PTSIZE_MIN  10
#define OSD_PTSIZE_MAX  40

#define OSD_BUFFLEN     512

static SDL_Color white = { 0xFF, 0xFF, 0xFF, 0 };
static SDL_Color black = { 0, 0, 0, 0 };

static TTF_Font *font = NULL;
uint16_t fontlineskip;
extern char has_osd;
extern SDL_Window *osd_window;


int
ttf_init(void)
{
  /* Initialize the TTF library */
  if (!TTF_WasInit())
    if (TTF_Init() < 0) {
      xerror("[SDL] Couldn't initialize TTF: %s\n", SDL_GetError());
    }

  /* Get the font path */
  const char *font_path = getenv("LEBINIOU_FONT");
  if (NULL == font_path) {
    VERBOSE(printf("[i] [SDL] LEBINIOU_FONT is not set, using\n"));
    VERBOSE(printf("[i] [SDL] '%s' as OSD font\n", OSD_FONT));
    font_path = OSD_FONT;
  } else {
    VERBOSE(printf("[i] [SDL] Using '%s' as OSD font\n", font_path));
  }

  /* Get the font size */
  const char *font_size = getenv("LEBINIOU_FONT_SIZE");
  int ptsize = OSD_PTSIZE;
  if (NULL != font_size) {
    long _ptsize = xstrtol(font_size);
    if ((_ptsize >= OSD_PTSIZE_MIN) && (_ptsize <= OSD_PTSIZE_MAX)) {
      ptsize = _ptsize;
      VERBOSE(printf("[i] [SDL] Font size set to %d\n", ptsize));
    } else {
      VERBOSE(printf("[!] [SDL] Invalid font size %ld, using %d\n", _ptsize, ptsize));
    }
  }

  /* Open the font file with the requested point size */
  font = TTF_OpenFont(font_path, ptsize);
  if (NULL == font) {
    VERBOSE(printf("[!] [SDL] %s, OSD is disabled.\n", SDL_GetError()));
    return 0;
  } else {
    TTF_SetFontStyle(font, TTF_STYLE_NORMAL);
    /* TTF_SetFontStyle(font, TTF_STYLE_BOLD); */
    fontlineskip = TTF_FontLineSkip(font);
    return 1;
  }
}


void
ttf_quit(void)
{
  if (NULL != font) {
    TTF_CloseFont(font);
  }
  TTF_Quit();
}


uint16_t
osd_print(const uint16_t x, uint16_t y,
          const uint8_t rev_x, const uint8_t rev_y,
          const char *fmt, ...)
{
  char str[OSD_BUFFLEN+1];
  va_list ap;
  SDL_Surface *text = NULL;
  SDL_Rect    dstrect;
  SDL_Color   fg_color;
  int out_width, out_height;

  SDL_GetWindowSize(osd_window, &out_width, &out_height);

  memset((void *)str, '\0', OSD_BUFFLEN * sizeof(char));
  assert(NULL != fmt);
  va_start(ap, fmt);
  vsprintf(str, fmt, ap); /* TODO vsnprintf */
  va_end(ap);

  fg_color = white;

  text = TTF_RenderText_Blended(font, str, black);

  if (NULL != text) {
    int dx, dy;

    dstrect.w = text->w;
    dstrect.h = text->h;
    for (dx = -2; dx <= 2; dx ++) {
      for (dy = -2; dy <= 2; dy ++) {
        dstrect.x = (rev_x) ? (out_width - x - text->w) : x;
        dstrect.y = (rev_y) ? (out_height - y - text->h) : y;
        dstrect.x += dx;
        dstrect.y += dy;
        SDL_BlitSurface(text, NULL, SDL_GetWindowSurface(osd_window), &dstrect);
      }
    }
    SDL_FreeSurface(text);

    text = TTF_RenderText_Blended(font, str, fg_color);
    dstrect.x = (rev_x) ? (out_width - x - text->w) : x;
    dstrect.y = (rev_y) ? (out_height - y - text->h) : y;
    SDL_BlitSurface(text, NULL, SDL_GetWindowSurface(osd_window), &dstrect);
    SDL_FreeSurface(text);

    y += TTF_FontLineSkip(font);
  }

  return y;
}
