#include <pthread.h>
#include "demo.h"

static void*
fadethread(void* vncp){
  struct timespec fade = { .tv_sec = 5, .tv_nsec = 0, };
  ncplane_fadeout(vncp, &fade);
  return NULL;
}

static struct ncplane*
outro_message(struct notcurses* nc, int* rows, int* cols){
  const char str0[] = " ATL, baby! ATL! ";
  const char str1[] = " throw your hands in the air ";
  const char str2[] = " hack on! —dank❤ ";
  int xstart = (*cols - (strlen(str1) + 4)) / 2;
  int ystart = *rows - 6;
  struct ncplane* on = notcurses_newplane(nc, 5, strlen(str1) + 4, ystart, xstart, NULL);
  if(on == NULL){
    return NULL;
  }
  cell bgcell = CELL_SIMPLE_INITIALIZER(' ');
  channels_set_bg_rgb(&bgcell.channels, 0x58, 0x36, 0x58);
  if(ncplane_set_default(on, &bgcell) < 0){
    return NULL;
  }
  ncplane_dim_yx(on, rows, cols);
  int ybase = 0;
  // bevel the upper corners
  if(ncplane_set_bg_alpha(on, CELL_ALPHA_TRANS)){
    return NULL;
  }
  if(ncplane_cursor_move_yx(on, ybase, 0)){
    return NULL;
  }
  if(ncplane_putsimple(on, ' ') < 0 || ncplane_putsimple(on, ' ') < 0){
    return NULL;
  }
  if(ncplane_cursor_move_yx(on, ybase, *cols - 2)){
    return NULL;
  }
  if(ncplane_putsimple(on, ' ') < 0 || ncplane_putsimple(on, ' ') < 0){
    return NULL;
  }
  // ...and now the lower corners
  if(ncplane_cursor_move_yx(on, *rows - 1, 0)){
    return NULL;
  }
  if(ncplane_putsimple(on, ' ') < 0 || ncplane_putsimple(on, ' ') < 0){
    return NULL;
  }
  if(ncplane_cursor_move_yx(on, *rows - 1, *cols - 2)){
    return NULL;
  }
  if(ncplane_putsimple(on, ' ') < 0 || ncplane_putsimple(on, ' ') < 0){
    return NULL;
  }
  if(ncplane_set_fg_rgb(on, 0, 0, 0)){
    return NULL;
  }
  if(ncplane_set_bg_rgb(on, 0, 180, 180)){
    return NULL;
  }
  if(ncplane_set_bg_alpha(on, CELL_ALPHA_OPAQUE)){ // FIXME use intermediate
    return NULL;
  }
  if(ncplane_putstr_aligned(on, ++ybase, str0, NCALIGN_CENTER) < 0){
    return NULL;
  }
  if(ncplane_putstr_aligned(on, ++ybase, str1, NCALIGN_CENTER) < 0){
    return NULL;
  }
  if(ncplane_putstr_aligned(on, ++ybase, str2, NCALIGN_CENTER) < 0){
    return NULL;
  }
  if(notcurses_render(nc)){
    return NULL;
  }
  cell_release(on, &bgcell);
  *rows = ystart;
  *cols = xstart;
  return on;
}

int outro(struct notcurses* nc){
  struct ncplane* ncp;
  if((ncp = notcurses_stdplane(nc)) == NULL){
    return -1;
  }
  int rows, cols;
  ncplane_erase(ncp);
  ncplane_dim_yx(ncp, &rows, &cols);
  int averr = 0;
  char* path = find_data("changes.jpg");
  struct ncvisual* ncv = ncplane_visual_open(ncp, path, &averr);
  free(path);
  if(ncv == NULL){
    return -1;
  }
  if(ncvisual_decode(ncv, &averr) == NULL){
    ncvisual_destroy(ncv);
    return -1;
  }
  if(ncvisual_render(ncv)){
    ncvisual_destroy(ncv);
    return -1;
  }
  int xstart = cols;
  int ystart = rows;
  struct ncplane* on = outro_message(nc, &ystart, &xstart);
  if(on){
    pthread_t tid;
    // will fade across 5s
    pthread_create(&tid, NULL, fadethread, ncp);
    struct timespec iterts;
    int targy = rows / 2 - (rows - ystart);
    ns_to_timespec(5000000000 / (ystart - targy), &iterts);
    int y;
    for(y = ystart - 1 ; y >= targy ; --y){
      nanosleep(&iterts, NULL);
      ncplane_move_yx(on, y, xstart);
      notcurses_render(nc);
    }
    ncplane_fadeout(on, &demodelay);
    pthread_join(tid, NULL);
    ncplane_destroy(on);
  }
  ncvisual_destroy(ncv);
  return on ? 0 : -1;
}
