// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <framebuffer.h>
#include <lib/gfx-font-data/gfx-font-data.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <xefi.h>

static efi_graphics_output_protocol* fb_get_gop() {
  static efi_graphics_output_protocol* gop = NULL;
  if (!gop) {
    gBS->LocateProtocol(&GraphicsOutputProtocol, NULL, (void**)&gop);
  }
  return gop;
}

uint32_t get_gfx_mode() {
  efi_graphics_output_protocol* gop = fb_get_gop();
  return gop->Mode->Mode;
}

uint32_t get_gfx_max_mode() {
  efi_graphics_output_protocol* gop = fb_get_gop();
  return gop->Mode->MaxMode;
}

uint32_t get_gfx_hres() {
  efi_graphics_output_protocol* gop = fb_get_gop();
  efi_graphics_output_mode_information* mode_info;
  size_t info_size = 0;
  efi_status status = gop->QueryMode(gop, gop->Mode->Mode, &info_size, &mode_info);
  if (EFI_ERROR(status)) {
    return 0;
  }
  return mode_info->HorizontalResolution;
}

uint32_t get_gfx_vres() {
  efi_graphics_output_protocol* gop = fb_get_gop();
  efi_graphics_output_mode_information* mode_info;
  size_t info_size = 0;
  efi_status status = gop->QueryMode(gop, gop->Mode->Mode, &info_size, &mode_info);
  if (EFI_ERROR(status)) {
    return 0;
  }
  return mode_info->VerticalResolution;
}

void set_gfx_mode(uint32_t mode) {
  efi_graphics_output_protocol* gop = fb_get_gop();
  if (!gop)
    return;
  if (mode >= gop->Mode->MaxMode) {
    printf("invalid framebuffer mode: %u\n", mode);
    return;
  }
  efi_status s = gop->SetMode(gop, mode);
  if (EFI_ERROR(s)) {
    printf("could not set mode: %s\n", xefi_strerror(s));
  }
  gBS->Stall(1000);
  gSys->ConOut->SetCursorPosition(gSys->ConOut, 0, 0);
}

void set_gfx_mode_from_cmdline(const char* fbres) {
  if (!fbres)
    return;
  efi_graphics_output_protocol* gop = fb_get_gop();
  if (!gop)
    return;

  uint32_t hres = 0;
  hres = atol(fbres);

  char* x = strchr(fbres, 'x');
  if (!x)
    return;
  x++;

  uint32_t vres = 0;
  vres = atol(x);
  if (!hres || !vres)
    return;

  uint32_t max_mode = gop->Mode->MaxMode;

  for (uint32_t i = 0; i < max_mode; i++) {
    efi_graphics_output_mode_information* mode_info;
    size_t info_size = 0;
    efi_status status = gop->QueryMode(gop, i, &info_size, &mode_info);
    if (EFI_ERROR(status)) {
      printf("Could not retrieve mode %d: %s\n", i, xefi_strerror(status));
      continue;
    }

    if (mode_info->HorizontalResolution == hres && mode_info->VerticalResolution == vres) {
      set_gfx_mode(i);
      return;
    }
  }
  printf("Could not find framebuffer mode %ux%u; using default mode = %ux%u\n", hres, vres,
         gop->Mode->Info->HorizontalResolution, gop->Mode->Info->VerticalResolution);
  gBS->Stall(5000000);
}

void print_fb_modes() {
  efi_graphics_output_protocol* gop = fb_get_gop();
  uint32_t max_mode = gop->Mode->MaxMode;
  uint32_t cur_mode = gop->Mode->Mode;
  for (uint32_t i = 0; i < max_mode; i++) {
    efi_graphics_output_mode_information* mode_info;
    size_t info_size = 0;
    efi_status status = gop->QueryMode(gop, i, &info_size, &mode_info);
    if (EFI_ERROR(status))
      continue;
    printf(" (%u) %u x %u%s\n", i, mode_info->HorizontalResolution, mode_info->VerticalResolution,
           i == cur_mode ? " (current)" : "");
  }
}

#include "logo.h"

static efi_graphics_output_blt_pixel font_white = {
    .Red = 0xFF,
    .Green = 0xFF,
    .Blue = 0xFF,
};

static efi_graphics_output_blt_pixel font_black = {
    .Red = 0x0,
    .Green = 0x0,
    .Blue = 0x0,
};

static efi_graphics_output_blt_pixel font_fuchsia = {
    .Red = 0xFF,
    .Green = 0x0,
    .Blue = 0x80,
};

void draw_logo() {
  efi_graphics_output_protocol* gop = fb_get_gop();
  if (!gop)
    return;

  const uint32_t h_res = gop->Mode->Info->HorizontalResolution;
  const uint32_t v_res = gop->Mode->Info->VerticalResolution;

  // Blank the screen, removing vendor UEFI logos
  gop->Blt(gop, &font_black, EfiBltVideoFill, 0, 0, 0, 0, h_res, v_res, 0);

  efi_graphics_output_blt_pixel* tmp;
  unsigned sz = sizeof(efi_graphics_output_blt_pixel) * logo_width * logo_height;
  if (EFI_ERROR(gBS->AllocatePool(EfiLoaderData, sz, (void*)&tmp))) {
    // Draw the Fuchsia stripe on the top of the screen
    gop->Blt(gop, &font_fuchsia, EfiBltVideoFill, 0, 0, 0, 0, h_res, v_res / 100, 0);
    return;
  }

  // Un-RLE the logo
  unsigned char* iptr = logo_rle;
  efi_graphics_output_blt_pixel* optr = tmp;
  unsigned entries = sizeof(logo_rle) / 2;
  while (entries-- > 0) {
    unsigned count = *iptr++;
    unsigned alpha = *iptr++;
    efi_graphics_output_blt_pixel px = {
        .Red = (alpha * 0xFF) / 255,
        .Green = 0,
        .Blue = (alpha * 0x80) / 255,
    };
    while (count-- > 0) {
      *optr++ = px;
    }
  }

  gop->Blt(gop, tmp, EfiBltBufferToVideo, 0, 0, h_res - logo_width - (h_res / 75),
           v_res - logo_height - (v_res / 75), logo_width, logo_height, 0);
}

static void putchar(efi_graphics_output_protocol* gop, const gfx_font* font, unsigned ch,
                    unsigned x, unsigned y, unsigned scale_x, unsigned scale_y,
                    efi_graphics_output_blt_pixel* fg, efi_graphics_output_blt_pixel* bg) {
  const uint16_t* cdata = font->data + ch * font->height;
  unsigned fw = font->width;
  for (unsigned i = 0; i <= font->height; i++) {
    uint16_t xdata = *cdata++;
    for (unsigned j = 0; j < fw; j++) {
      gop->Blt(gop, (xdata & 1) ? fg : bg, EfiBltVideoFill, 0, 0, x + scale_x * j, y + scale_y * i,
               scale_x, scale_y, 0);
      xdata >>= 1;
    }
  }
}

void draw_text(const char* text, size_t length, const fb_font* font, int x, int y) {
  efi_graphics_output_protocol* gop = fb_get_gop();
  efi_graphics_output_blt_pixel* fg_color = &font_white;
  if (!gop)
    return;

  if (font->color != NULL) {
    fg_color = font->color;
  }

  size_t offset = 0;
  size_t scale = 1;
  for (size_t i = 0; i < length; ++i) {
    unsigned char c = text[i];
    if (c > 127)
      continue;
    putchar(gop, font->font, c, x + offset, y, scale, scale, fg_color, &font_black);
    offset += font->font->width * scale;
  }
}

void draw_nodename(const char* nodename) {
  efi_graphics_output_protocol* gop = fb_get_gop();
  if (!gop)
    return;

  const fb_font font = {
      .font = &gfx_font_18x32,
      .color = &font_white,
  };

  const uint32_t h_res = gop->Mode->Info->HorizontalResolution;
  const uint32_t v_res = gop->Mode->Info->VerticalResolution;
  size_t length = strlen(nodename);
  draw_text(nodename, length, &font, h_res - (length + 1) * font.font->width,
            v_res / 100 + font.font->height);
}

void draw_version(const char* version) {
  efi_graphics_output_protocol* gop = fb_get_gop();
  if (!gop)
    return;

  const char* prefix = "GigaBoot 20X6 - Version";
  size_t prefix_len = strlen(prefix);
  size_t version_len = strlen(version);

  const fb_font font = {
      .font = &gfx_font_9x16,
      .color = &font_fuchsia,
  };

  draw_text(prefix, prefix_len, &font, 0, 0);
  draw_text(version, version_len, &font, (prefix_len + 1) * font.font->width, 0);
}
